Links2004 / arduinoWebSockets

arduinoWebSockets
GNU Lesser General Public License v2.1
1.89k stars 555 forks source link

crash and reboot when WEBSOCKETS_SERVER_CLIENT_MAX is exceeded #644

Closed joliclic closed 3 years ago

joliclic commented 3 years ago

When the number of connected clients exceeds the max défined by WEBSOCKETS_SERVER_CLIENT_MAX, the program crashes and the card reboots.

The following program was used, on a esp8266 card (Wemos D1 mini), with WebSockets 2.3.5. I have tried to modify WEBSOCKETS_SERVER_CLIENT_MAX in WebSocketsServer.h, but for every value the program crashes as soon as I try to connect (value+1) clients. It would be better if the new connection is refused and ignored.

ino:

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <WebSocketsServer.h>

#define USE_SERIAL Serial

WebSocketsServer webSocket = WebSocketsServer(81);

void webSocketEvent
(uint8_t a_num, WStype_t a_type, uint8_t* a_payload, size_t a_length) {
    switch(a_type) {
        case WStype_DISCONNECTED:
            USE_SERIAL.printf("[%u] Disconnected!\n", a_num);
            break;
        case WStype_CONNECTED: {
                IPAddress ip = webSocket.remoteIP(a_num);
                USE_SERIAL.printf(
                    "[%u] Connected from %d.%d.%d.%d url: %s\n",
                    a_num, ip[0], ip[1], ip[2], ip[3], a_payload
                );
                webSocket.sendTXT(a_num, "Connected");
            break;
        }
        case WStype_TEXT:
            webSocket.sendTXT(a_num, "receive a message");
            break;
        case WStype_BIN:
            USE_SERIAL.printf("[%u] get binary length: %u\n", a_num, a_length);
            hexdump(a_payload, a_length);
            // webSocket.sendBIN(num, payload, length);
            break;
    }
}

void setup() {
    USE_SERIAL.begin(115200);
    //USE_SERIAL.setDebugOutput(true);

    USE_SERIAL.println();
    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(250);
    }
    WiFi.disconnect();
    WiFi.hostname("myhostname");
    WiFi.mode(WIFI_STA);
    IPAddress staticIP(192, 168, 0, 17);
    IPAddress gateway(192, 168, 0, 255);
    IPAddress subnet(255, 255, 255, 0);
    WiFi.config(staticIP, gateway, subnet);

    WiFi.begin("SSID", "password");
    while(WiFi.status() != WL_CONNECTED) {
        delay(100);
        USE_SERIAL.print(".");
    }
    USE_SERIAL.println();

    USE_SERIAL.println();
    USE_SERIAL.print("Connected, IP address: ");
    USE_SERIAL.println(WiFi.localIP());
    USE_SERIAL.printf("Connection status: %d\n", WiFi.status());

    webSocket.begin();
    webSocket.onEvent(webSocketEvent);
}

void loop() {
    webSocket.loop();
}

JavaScript code used in the browser, (client):

let gServers = [];

document.addEventListener('DOMContentLoaded', function(e) {
    for (let i = 0; i < 6; i++) {
        let websocket = new WebSocket('ws:/192.168.0.17:81');
        let servername = 'test ' + i;
        websocket.addEventListener('open', function (evt) {
            console.log ('WebSocket ' + servername + ' is open now.');
        });
        websocket.addEventListener('message', function (evt) {
            console.log ('receive the message:');
            console.log (evt.data);
        });
        websocket.addEventListener('close', function(evt) {
            console.log ('WebSocket ' + servername + ' is closed now.');
            console.log (evt);
        });
        websocket.addEventListener('error', function(evt) {
            console.log ('WebSocket ' + servername + ' error');
            console.log (evt);
        });

        gServers.push(websocket);
    }
});

The decoded exception:

Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
PC: 0x40207cdb: WebSocketsServerCore::dropNativeClient(WSclient_t*) at /home/moi/Arduino/libraries/WebSockets/src/WebSocketsServer.cpp line 519
EXCVADDR: 0x00000008

Decoding stack results
0x40203ed9: WebSocketsServerCore::handleNewClient(WiFiClient*) at /home/moi/Arduino/libraries/WebSockets/src/WebSocketsServer.cpp line 610
0x40203f27: WebSocketsServer::handleNewClients() at /home/moi/Arduino/libraries/WebSockets/src/WebSocketsServer.cpp line 635
0x40204574: WebSocketsServer::loop() at /home/moi/Arduino/libraries/WebSockets/src/WebSocketsServer.cpp line 945
0x40201294: loop() at /home/moi/dev/bug-max-connections-ws/bug_maxconnect/bug_maxconnect.ino line 74
resolvethis commented 3 years ago

I have the same issue and I agree with the proposed solution. You could send some defined close code: https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.2

I use version 2.3.5 but I get a slightly different stack result (line numbers):

Core 1 register dump:
PC      : 0x4016d807  PS      : 0x00060030  A0      : 0x800d7195  A1      : 0x3ffb1f10  
A2      : 0x3ffc17f4  A3      : 0x00000000  A4      : 0x00000005  A5      : 0x3ffc1c20  
A6      : 0x00000001  A7      : 0x000000cc  A8      : 0x800d7097  A9      : 0x3ffb1ef0  
A10     : 0x00000001  A11     : 0x3ffc1b54  A12     : 0x00000000  A13     : 0x3ffb1f18  
A14     : 0x00000004  A15     : 0x3ffc5548  SAR     : 0x0000001b  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000008  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x4016d807:0x3ffb1f10 0x400d7192:0x3ffb1f30 0x400d71c9:0x3ffb1f50 0x400d7ad9:0x3ffb1f70 0x400d4096:0x3ffb1f90 0x400db53c:0x3ffb1fb0 0x400899aa:0x3ffb1fd0

EXCVADDR: 0x00000008

Decoding stack results
0x4016d807: WebSocketsServerCore::dropNativeClient(WSclient_t*) at C:\Users\mvrm\Documents\Arduino\libraries\WebSockets\src\WebSocketsServer.cpp line 519
0x400d7192: WebSocketsServerCore::handleNewClient(WiFiClient*) at C:\Users\mvrm\Documents\Arduino\libraries\WebSockets\src\WebSocketsServer.cpp line 622
0x400d71c9: WebSocketsServer::handleNewClients() at C:\Users\mvrm\Documents\Arduino\libraries\WebSockets\src\WebSocketsServer.cpp line 645
0x400d7ad9: WebSocketsServer::loop() at C:\Users\mvrm\Documents\Arduino\libraries\WebSockets\src\WebSocketsServer.cpp line 944
0x400d4096: loop() at C:\data\personal\huis\alarm\alarm-front/alarm-front.ino line 60
0x400db53c: loopTask(void*) at C:\Users\mvrm\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\main.cpp line 23
0x400899aa: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143```
mvermand22 commented 3 years ago

Any progress or workaround on this issue?

mvermand22 commented 3 years ago

I created a pull request to fix this issue: https://github.com/Links2004/arduinoWebSockets/pull/708