lasselukkari / aWOT

Arduino web server library.
MIT License
294 stars 42 forks source link

Intermittent ERR_CONTENT_LENGTH_MISMATCH #89

Closed Jauwaad closed 3 years ago

Jauwaad commented 3 years ago

Both version 1 and version 3 end up having this error on an Arduino MKR WiFi 1010. This error is very intermittent.

lasselukkari commented 3 years ago

Please post an example sketch that that can be used to reproduce the error.

lasselukkari commented 3 years ago

Most likely the same problems as in your other issue. Try explicitly closing the connection. Anyway this error is not coming from the library itself so a bit more context would help.

Jauwaad commented 3 years ago

Closing the connection does not resolve this issue. It looks like the file download is interrupted.

Screen Shot 2020-12-19 at 10 14 26 PM

The stylesheet file is 26.5kB and the script file 87.6kB

lasselukkari commented 3 years ago

Could you please attach the project source code so I can see what is going wrong. It seems that for some reason your body has a different size than your headers say it would be.

Have you tried to take a look what is actually transferred? Does curl work? Is it always the same file that fails?

You are not really making this easy for me.

lasselukkari commented 3 years ago

It seems that the WiFi library you are using does not implement proper flushing: https://github.com/arduino-libraries/WiFiNINA/blob/master/src/WiFiClient.cpp#L259-L261

Try adding delay(1000); before you disconnect the client. If that makes it reliable gradually reduce the delay to a smaller number,

lasselukkari commented 3 years ago

According to the github issues of the WiFI library there has been a lot of issues in the past. What firmware version you have installed for the wifi module?

Jauwaad commented 3 years ago

Apologize for making this hard. Still trying to figure this out. Adding a delay didn't resolve the issue. Using the latest firmware version 1.3.0.

lasselukkari commented 3 years ago

Is it always the same file? Does it work with curl? Can you record the traffic with wireshark? Could you share the source code as zip file?

The latest firmware seems to be 1.4.1.

Jauwaad commented 3 years ago

I updated the NINA firmware to 1.4.1. Same error continues. Curl gives the following error assuming an error occurs retrieving the larger file

curl 'http://192.168.86.41/static/js/2.cb5a9df6.chunk.js' -v --output - . . .

??<%??6*h?&

The source code has some proprietary information. I will try to zip up the general contents and send it over. After which I'll troubleshoot using wireshark.

lasselukkari commented 3 years ago

The gemerated StaticFiles.h is enough for me.

Jauwaad commented 3 years ago

See attached

StaticFiles.h.zip

lasselukkari commented 3 years ago

I tested the file with ESP8266 and everything works as expected.

Especially as the problem happens intermittently and during the response writing it starts to sound like that the problem is somewhere in the WiFiNINA stack. I just ordered the board so I can try it out. I expect it to take until next week to arrive because of the holidays.

I have attached the sketch I tested with the esp8266. It's been modified so that it should work with the WiFiNINA. Could you try it out to make sure that the problem still persists with this so that we can be sure the problems is not somewhere else in your code.

TestServer.zip

Jauwaad commented 3 years ago

Same issue persists with the TestServer. I added client.stop after processing and a get call to /api/connection.

In addition, occasionally I got the following error which I didn't get previously

GET http://192.168.86.41/static/js/2.cb5a9df6.chunk.js net::ERR_CONTENT_DECODING_FAILED 200 (OK)

lasselukkari commented 3 years ago

Could you change your code to have this and see if the library itself detects the error.

void loop() {
  WiFiClient client = server.available();

  if (client.connected()) {
    app.process(&client);
    if(client.getWriteError()){
      Serial.println("Client failed to write");
    }
    client.stop();
  }
}

I have never seen the writes to fail with any other hardware combination so there has been no reason trying to detect them in any way.

My MKR WiFi 1010 board is on it's way. I should get it before the weekend.

Jauwaad commented 3 years ago

Yes. It reported client failed to write.

On Mon, Dec 21, 2020 at 1:42 PM Lasse Lukkari notifications@github.com wrote:

Could you change your code to have this and see if the library itself detects the error.

void loop() { WiFiClient client = server.available();

if (client.connected()) { app.process(&client); if(client.getWriteError()){ Serial.println("Client failed to write"); } client.stop(); } }

I have never seen the writes to fail with any other hardware combination so there has been no reason trying to detect them in any way.

My MKR WiFi 1010 board is on it's way. I should get it before the weekend.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749212312, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3F6MTYCENXM7XHRJDDSV66NJANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

Maybe making the write buffer smaller (or bigger) could help. Try changing this value here: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.h#L59. You can start with some really small value and if works try increasing it until it starts to fail again. I will try dig in to the firmware code and see what are the possible error cases.

Jauwaad commented 3 years ago

The error occurs on both ends. The larger buffers end up getting more errors.

On Mon, Dec 21, 2020 at 2:29 PM Lasse Lukkari notifications@github.com wrote:

Maybe making the write buffer smaller (or bigger) could help. Try changing this value here: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.h#L59. You can start with some really small value and if works try increasing it until it starts to fail again. I will try dig in to the firmware code and see what are the possible error cases.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749233420, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3CB5UPDMOE6CJU4IMLSV7D47ANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

I took a look at the firmare https://github.com/arduino/nina-fw. I did not realise it is built using the ESP32 Arduino core. The core files bundled with the project are rather outdated and seem to be maintained and modified manually. You can comapre the edit times between https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src and https://github.com/arduino/nina-fw/tree/master/arduino/libraries/WiFi/src. Also the ESP-IDF dates back to a year ago.

Considering how unstable the ESP32 Arduino core has been so far I'm not really surprised that we see these problems.

To be honest my advice would be to stay away from this software/hardware stack combination. It's a mess. I will try to see if there is something I can do once I receive the board but I would seriously reconsider the options.

Jauwaad commented 3 years ago

Thank you for your response. We’re tied to the MKRWifi 1010, any suggestions on the choice of library is appreciated. Everything else works perfectly. We are using WiFi for other communication over tcp and not seeing any data drops. TCP communications are in binary and continuous and fast. This leads me to think that there is something in the aWOT code that doesn’t work well with the board

On Mon, Dec 21, 2020 at 3:14 PM Lasse Lukkari notifications@github.com wrote:

I took a look at the firmare https://github.com/arduino/nina-fw. I did not realise it is built using the ESP32 Arduino core. The core files bundled with the project are rather outdated and seem to be maintained and modified manually. You can comapre the edit times between https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src and https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src. Also the ESP-IDF dates back to a year ago.

Considering how unstable the ESP32 Arduino core has been so far I'm not really surprised that we see these problems.

To be honest my advice would be to stay away from this software/hardware stack combination. It's a mess. I will try to see if there is something I can do once I receive the board but I would seriously reconsider the options.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749248308, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3BI54FC5XMIS6MWIRLSV7JGTANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

The aWOT library uses the Stream class for reading and writing (aWOT.h#L257).

The Stream class is a base class that is extended by the various WiFi and Ethernet libraries. Serial ports are also Streams as well as the SD card file instances and so on. This means that aWOT codebase is almost hardware agnostic. You can even type in the HTTP requests using the serial monitor if you add if (Serial.available()) {app.process(&Serial);} to your loop. At the point where our problems happen the library just does just simple writes. There is really no way to use the Stream write functions in a "wrong" way so that it sometimes works and sometimes doesn't.

Have you been running a tcp server previously? I can see that just running a client is a lot less error prone. I believe we can most likely reproduce the behavior by emulating the same writes to a connected client without using the aWOT library. Maybe that way it would be easier to find the limitation we hitting now.

Jauwaad commented 3 years ago

I am running two instances of a TCP server along with the Webserver running using aWOT. The communication is less forgiving on the binary protocols and I don’t see any errors running it continuously for days.

On Mon, Dec 21, 2020 at 4:44 PM Lasse Lukkari notifications@github.com wrote:

The aWOT library uses the Stream class for reading and writing ( aWOT.h#L257 https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.h#L257).

The Stream class is a base class that is extended by the various WiFi and Ethernet libraries. Serial ports are also Streams as well as the SD card file instances and so on. This means that aWOT codebase is almost hardware agnostic. You can even type in the HTTP requests using the serial monitor if you add if (Serial.available()) {app.process(&Serial);} to your loop. At the point where our problems happen the library just does just simple writes. There is really no way to use the Stream write functions in a "wrong" way so that it sometimes works and sometimes doesn't.

Have you been running a tcp server previously? I can see that just running a client is a lot less error prone. I believe we can most likely reproduce the behavior by emulating the same writes to a connected client without using the aWOT library. Maybe that way it would be easier to find the limitation we hitting now.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749274842, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3AOFCI6YP6MCZFOWYLSV7TWPANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

Does the error ever happen with smallest files?

Jauwaad commented 3 years ago

No, it doesn't.

On Mon, Dec 21, 2020 at 4:57 PM Lasse Lukkari notifications@github.com wrote:

Does the error ever happen with smallest files?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749278071, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3CXW7NDWB7L3P473OLSV7VH5ANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

You could try to add some artificial delay() before this line: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.cpp#L162 and maybe before this one too: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.cpp#L188

This would limit the frequency we call the write api that goes through rather inefficient SPI protocol to the ESP32 running an outdated software with tons of know bugs unfixed trying to juggle all the open connections while keeping the wifi connection working at the same time. Maybe the poor thing would not get exhausted anymore.

Jauwaad commented 3 years ago

I added from 1 - 20ms delays before and after. The error still popped up.

On Mon, Dec 21, 2020 at 5:08 PM Lasse Lukkari notifications@github.com wrote:

You could try to add some artificial delay() before this line: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.cpp#L162 and maybe before this one too: https://github.com/lasselukkari/aWOT/blob/master/src/aWOT.cpp#L188

This would limit the frequency we call the write api that goes through rather inefficient SPI protocol to the ESP32 running an outdated software with tons of know bugs unfixed trying to juggle with all the open connections while keeping the wifi connection working at the same time. Maybe the poor thing would not get exhausted anymore.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lasselukkari/aWOT/issues/89#issuecomment-749281018, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVCW3FR3M3LD3NNS5K2DL3SV7WRLANCNFSM4VCBCXOQ .

lasselukkari commented 3 years ago

Someone else seems to have the same problem here: https://github.com/arduino-libraries/WiFiNINA/issues/129

lasselukkari commented 3 years ago

The board arrived today. That was faster than I expected.

Here is a sketch that has been modified from the WiFiNINA WiFiWebServer example.

#include <SPI.h>
#include <WiFiNINA.h>

#define WIFI_SSID ""
#define WIFI_PASSWORD ""

WiFiServer server(80);

void setup() {
  Serial.begin(9600);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP());

  server.begin();
}

void loop() {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/plain");
          client.println("Content-Length: 100000");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println();
          for (int i = 0; i < 100; i++) {
            client.print(
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
              "****************************************************************************************************"
            );
          }

          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }

    if (client.getWriteError()) {
      Serial.println("Client write error detected");
    }

    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

With a few browser reloads I was able to reproduce the same behaviour you are seeing.

Screenshot 2020-12-22 at 22 48 43

I think this discussion needs to be moved to the WiFiNINA repository because the problem is not in this library.

lasselukkari commented 3 years ago

What buffer sizes did you actually try? I see that with 10 it seems to work reliably but it's really slow because it's writing so small chunks.

lasselukkari commented 3 years ago

I'm closing this issue because the problem is not in this library. Let's continue the discussion in the nina-fm repository.

lasselukkari commented 3 years ago

The bug is fixed once these get merged and released: https://github.com/arduino-libraries/WiFiNINA/pull/146 https://github.com/arduino/nina-fw/pull/62

Jauwaad commented 3 years ago

Thanks a lot. Were you able to test it out. Looking forward to the release

lasselukkari commented 3 years ago

Yes i tested it with your StaticFiles.h and it works fine now. I just need to figure out some fun project for the board I bought for testing this :).