Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem in NetworkClient::connected() #10559

Open
1 task done
NPaolini opened this issue Nov 3, 2024 · 16 comments · May be fixed by #10640
Open
1 task done

Problem in NetworkClient::connected() #10559

NPaolini opened this issue Nov 3, 2024 · 16 comments · May be fixed by #10640
Assignees
Labels
Status: Awaiting triage Issue is waiting for triage

Comments

@NPaolini
Copy link

NPaolini commented Nov 3, 2024

Board

ESP32

Device Description

DOIT ESP32 DEVKIT V1

Hardware Configuration

almost all GPIO are connected

Version

v3.0.5

IDE Name

Arduino IDE

Operating System

Windows

Flash frequency

80 MHz

PSRAM enabled

no

Upload speed

921600

Description

With recv() in MSG_DONTWAIT the errno is not reset when recv() returns zero, not because the connection is terminated, but because there is no data. My solution is to reset errno before call to recv(). The full explanation is in 'https://forum.arduino.cc/t/errore-nel-file-appdata-local-arduino15-packages-esp32-hardware-esp32-3-0-x-libraries-network-src-networkclient-cpp/1317872/3'

Sketch

any web server

Debug Message

remote connection closed

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@NPaolini NPaolini added the Status: Awaiting triage Issue is waiting for triage label Nov 3, 2024
@NPaolini
Copy link
Author

NPaolini commented Nov 3, 2024

Ops ... Version v3.0.7

@NPaolini
Copy link
Author

NPaolini commented Nov 6, 2024

https://www.ennepisoft.it/test_esp32/test_esp32.php
there is the project that demonstrates the reported problem, the usage information in the 'readme.txt' file (sorry, it's in Italian)

@NPaolini
Copy link
Author

NPaolini commented Nov 8, 2024

hi, this is a more 'elegant' solution to the problem. It is likely that the cause comes from using an SD card to read the site files from which could set errno to some error code. If the link (.php) to the site is a problem, I put the link directly to the zipped test_file

@NPaolini
Copy link
Author

NPaolini commented Nov 8, 2024

uint8_t NetworkClient::connected() {
  if (fd() == -1 && _connected) {
    stop();
  }
  if (_connected) {
    uint8_t dummy;
//#define RESET_ERRNO
#ifdef RESET_ERRNO
    errno = ENOENT; // <= aggiunto
    int res = recv(fd(), &dummy, 0, MSG_DONTWAIT);
    if(res > 0)
      Serial.printf("recv return %d byte\n", res);
#else
    int res = recv(fd(), &dummy, 1, MSG_DONTWAIT | MSG_PEEK);
#endif
    // avoid unused var warning by gcc
    (void)res;
    // recv only sets errno if res is <= 0
    if (res <= 0) {
      switch (errno) {
        case EWOULDBLOCK:
        case ENOENT:  //caused by vfs
          _connected = true;
          break;
        case ENOTCONN:
        case EPIPE:
        case ECONNRESET:
        case ECONNREFUSED:
        case ECONNABORTED:
          _connected = false;
          log_d("Disconnected: RES: %d, ERR: %d", res, errno);
          break;
        default:
          log_i("Unexpected: RES: %d, ERR: %d", res, errno);
          _connected = true;
          break;
      }
    } else {
      _connected = true;
    }
  }
  return _connected;
}

@NPaolini
Copy link
Author

NPaolini commented Nov 11, 2024

I compared the WebServer library with the 'cotestatnt' library and I saw that the main difference of the handleClient() (in web_server.cpp) is the presence, in the core, of the following piece of code:

            if (_currentClient.isSSE()) {
              _currentStatus = HC_WAIT_CLOSE;
              _statusChange = millis();
              keepCurrentClient = true;
            }

I commented it and it didn't give that problem anymore, but if that code exists it has its reason and I think the solution I proposed is more valid.
I wanted to try the 'ESP_Async_WebServer' (I think it's yours) and I couldn't get it to work.
If it has to load a few files or in any case small in size it's ok (e.g. the login page), but when it passes to the index it gets stuck in write().
Even if it's not the fault of this code that takes care of the transfer, I'm posting it for completeness:

//---------------------------------------
char g_Buff2[1024 * 4];
#define chunk g_Buff2
#define sizeChunk (sizeof(chunk))
//---------------------------------------
template<typename T> void loadAndsendFile(AsyncWebServerRequest* request, T filename, int mime) 
{
  DEBUG_WEB(Serial.printf("FileToSend:%s, mime:%s\n", filename, getContentType(mime)))
  if (!openFile(filename)) {
    handle404(request);
    return;
    }
  int32_t _dim = myFile.size();
  AsyncClient* client = request->client();
  DEBUG_WEB(Serial.printf("Client %s, dim:%d\n", (client ? "Ok" : "Err"), _dim))
  sendHeader(client, mime, _dim, (eHTML == mime) ? no_cache : ok_cache);
  int32_t dim = _dim;
  int fail = 0;
  while(dim > 0 && fail < 5) {
    int len = min((unsigned int)dim, sizeChunk);
    len = myFile.read((uint8_t*)chunk, len);
    if (!len)
      break;
    bool inside = dim > sizeChunk;
    const char* t = (const char*)chunk;
    fail = 0;
    do {
      // non cambia nulla tra i due
//      int sent = client->write(t, len);
      int sent = client->write(t, len, inside ? ASYNC_WRITE_FLAG_MORE : 0);
      DEBUG_WEB(Serial.printf("Dim =%d, Remain=%d, Len=%d, Sent=%d\n", _dim, dim, len, sent))
      dim -= sent;
      if(sent == len)
        break;
      t += sent;
      len -= sent;
      vTaskDelay(10);
      if(!sent)
        ++fail;
      } while(fail < 5);
    }   
  DEBUG_WEB(if(dim) Serial.println(" Failed "); else Serial.println(" Done "))
  myFile.close();
}
//-------------------------------------------------------------------

I prepared a couple of logs, one when it tries to load the index, the other directly putting the name of a fairly large image.
The direct links (without even zipping them) are:
log_site.txt
only_big_file.txt

What could it depend on?

If you want (and you are interested) I can prepare the whole folder or you can use the one already linked and I will add only the modified files

@EmileSpecialProducts
Copy link

EmileSpecialProducts commented Nov 19, 2024

It looks like I have the same issue that you have and you can find my one file project on this github page, https://github.com/EmileSpecialProducts/ESP-SPIFFS-Web-Server
The code works on the ESP32-S3 ( Arduino 2.0.17 ) But not on the 3.0.7
Core Debug level : Debug
in Chrome I get the Error (failed)net::ERR_CONNECTION_RESET
The ESP debug logs I find this :
[ 22053][D][NetworkClient.cpp:568] connected(): Disconnected: RES: 0, ERR: 128
The error 128 #define ENOTCONN 128 /* Socket is not connected */

The project is a simple web server that servs files form the SPIFFS and has a Wifi-manager and OTA update.

http://xxx.xxx.xxx.xxx/
This will get a list of the files in the SPIFFS
http://xxx.xxx.xxx.xxx/list?dir=/

I see the error also on the ESP32-C6.

@NPaolini
Copy link
Author

While waiting for them to insert the patch I suggested you can directly modify the code by changing, in 'NetworkClient.cpp' the line:

int res = recv(fd(), &dummy, 0, MSG_DONTWAIT);

with:

int res = recv(fd(), &dummy, 1, MSG_DONTWAIT | MSG_PEEK);

in the function 'uint8_t NetworkClient::connected()'

@EmileSpecialProducts
Copy link

👍
Thanks for the suggestion.
I have tested it on a ESP32-S3 and ESP32-C6 and it will resoles the Issue

@lucasssvaz
Copy link
Collaborator

Could you create a minimal reproducible example and list what need to be done step-by-step to reproduce this issue ? I tried reproducing it but I did not found any issue (besides the debug message). The fix suggested also did not change anything for me.

@NPaolini
Copy link
Author

Sorry, I forgot to say that you need to set the specific bits to enable debugging, from serial you need to give the command: cmd=debug:80# or cmd=debug-bits:4,6,#.
Anyway, you should have seen the lack of loading of images in the browser. In the minimal version I will put in debug directly from the setup.
Have you created at least one user to log in? Because the login window does not cause problems.

@EmileSpecialProducts
Copy link

EmileSpecialProducts commented Nov 21, 2024

Could you create a minimal reproducible example and list what need to be done step-by-step to reproduce this issue ? I tried reproducing it but I did not found any issue (besides the debug message). The fix suggested also did not change anything for me.

You can use my project ESP-LittleFS-Web-Server. and you only need the ESP-LittleFS-Web-Server.ino file and works on all ESP types ( i have seen the issue on C6/S3, have not tested it on other devices)
It is a small web server that uses the LittleFS to download and upload files ( and you can edit them :-) ) and has a file tree
in the Chrome network window you can see the network errors (failed)net::ERR_CONNECTION_RESET when using 3.0.7 ( 2.0.17 works fine)
changing, in 'NetworkClient.cpp'
int res = recv(fd(), &dummy, 0, MSG_DONTWAIT);
with:
int res = recv(fd(), &dummy, 1, MSG_DONTWAIT | MSG_PEEK);
Also works fine

@NPaolini
Copy link
Author

I have prepared a minimal version that recreates the problem. It is in the same place as the 'almost complete' version:
test_esp32
Useful information is in the 'readme.txt' file.

@lucasssvaz
Copy link
Collaborator

lucasssvaz commented Nov 22, 2024

Could you create a minimal reproducible example and list what need to be done step-by-step to reproduce this issue ? I tried reproducing it but I did not found any issue (besides the debug message). The fix suggested also did not change anything for me.

You can use my project ESP-LittleFS-Web-Server. and you only need the ESP-LittleFS-Web-Server.ino file and works on all ESP types ( i have seen the issue on C6/S3, have not tested it on other devices) It is a small web server that uses the LittleFS to download and upload files ( and you can edit them :-) ) and has a file tree in the Chrome network window you can see the network errors (failed)net::ERR_CONNECTION_RESET when using 3.0.7 ( 2.0.17 works fine) changing, in 'NetworkClient.cpp' int res = recv(fd(), &dummy, 0, MSG_DONTWAIT); with: int res = recv(fd(), &dummy, 1, MSG_DONTWAIT | MSG_PEEK); Also works fine

I still don't get any errors (besides the obvious missing files):

image

@lucasssvaz
Copy link
Collaborator

lucasssvaz commented Nov 22, 2024

Ok, managed to reproduce it. I will open a PR.

@NPaolini
Copy link
Author

ok thanks, but the return zero can be due in three cases:

  1. remote connection closed, sets errno
  2. there is no data in the buffer, sets errno
  3. there is data but we have requested zero, does not set errno (and here is the error because errno could have assumed, previously, any value)

@lucasssvaz
Copy link
Collaborator

Updated description

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting triage Issue is waiting for triage
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants