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

Multiple polls for 1 websocket client when using firefox as client #58

Open
chubby1968 opened this issue Dec 11, 2019 · 2 comments
Open
Assignees
Labels
possible-bug Something isn't working, and I think it is a bug
Projects

Comments

@chubby1968
Copy link

Describe the bug
ESP32 is configured as server that accepts multiple clients. When connecting from firefox browser using server.poll(), two clients are registered (in most cases).

When this happens, no more code is executed. (It appears to be trapped in handshake part of server.accept() ).

To Reproduce
Using below code, connect to the esp32 board from firefox browser.

  • Library version 0.4.14
  • Board: ESP32-CAM
  • Firefox 71.0 (64-bit)

Expected behavior
Only 1 client is added to the list for each new connection (which is what happens in chrome).

Code

#include <WiFi.h>
#include <ArduinoWebsockets.h>
using namespace websockets;

const char *ssid = "xxxx";
const char *password = "xxxx";
const int maxClients = 4; // Accept up to 4 connections

WebsocketsServer server;
WebsocketsClient clients[maxClients];
int nClients = 0;

void setup()
{
  Serial.begin(115200);
  while (!Serial)
    ;

  // WIFI SETUP
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected, IP: ");
  Serial.println(WiFi.localIP());

  // WEBSOCKET: Open websocket on port 80
  server.listen(80);
  Serial.print("Is server live? ");
  Serial.println(server.available());
}

void loop()
{
  if (server.available())
  {
    // if there is a client that wants to connect
    if (server.poll() && nClients < maxClients)
    {
      //accept the connection and register callback
      Serial.print("Accepting a new client! Number of clients accepted: ");
      Serial.println(nClients + 1);
      WebsocketsClient client = server.accept();
      client.onMessage(onMessage);

      // store it for later use
      clients[nClients] = client;
      nClients++;
      delay(10);
    }

    // check for updates in all clients
    pollAllClients();

    delay(10);
  }
}

// this method goes thrugh every client and polls for new messages and events
void pollAllClients()
{
  for (int i = 0; i < nClients; i++)
  {
    clients[i].poll();
  }
}

// this callback is common for all clients, the client that sent that
// message is the one that gets the echo response
void onMessage(WebsocketsClient &client, WebsocketsMessage message)
{
  Serial.print("Got Message: ");
  Serial.print(message.data());
  Serial.println(", Sending Echo.");
  client.send("Echo: " + message.data());
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <link rel="stylesheet" href="../css/style.css" />
        <script src="../js/websocket.js" defer></script>
        <title>Websocket demo</title>
    </head>
    <body>
        <table>
            <thead>
                <th>Status</th>
                <th>Messages received</th>
            </thead>
            <tbody>
                <td id="status">Not connected</td>
                <td id="messages"></td>
            </tbody>
        </table>
        <form>
            <input type="button" id="msg_button" value="Send a msg" />
            <input type="text" placeholder="IP of server" name="IP" id="IP" value="" />
            <input type="button" id="IP_button" value="Configure IP" />
        </form>
    </body>
</html>
let messages = document.querySelector("#messages");
let status = document.querySelector("#status");
let ws;

document.querySelector("#IP_button").onclick = () => {
    
    if(typeof ws !== 'undefined'){
        ws.close();
    }
    ws = new WebSocket("ws://" + document.querySelector("#IP").value);
    status.innerHTML = "Websocket " + ws.readyState;

    ws.onopen = () => {
        status.innerHTML = "Websocket open";
        let i = 0;

        document.querySelector("#msg_button").onclick = () => {
            console.log("click");
            ws.send(i++);
        };

        ws.onmessage = event => {
            console.log(event);
            let txt = messages.innerHTML;
            messages.innerHTML = txt + "<br>" + event.data;
        };
    };

    ws.onclose = () => {
        status.innerHTML = "Websocket closed";
    };

    ws.onerror = event => {
        console.log(event);
        status.innerHTML = "Cannot connect to " + event.target.url;
    };
};
@gilmaimon gilmaimon added this to To do in Bugfixes via automation Dec 11, 2019
@gilmaimon gilmaimon added the possible-bug Something isn't working, and I think it is a bug label Dec 11, 2019
@gilmaimon
Copy link
Owner

gilmaimon commented Dec 17, 2019

Hi,

So, I was able to reproduce. The problem as far as I understand it has nothing to do with the library itself, it seems like esp32's WiFiServer impl claims that there is a client when there is not.
I will keep looking into it, meanwhile, you can check if the client that you got is connected by calling client.available. If it returns false, just skip that client.

Gil.

@Cnets-io
Copy link

Was there any solution to this? I am working with this otherwise great implementation, but looping even for 1 client does not seem to work. Always gets disconnected after the initial message was properly received (without me calling cloe() on the server)...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
possible-bug Something isn't working, and I think it is a bug
Projects
Bugfixes
  
To do
Development

No branches or pull requests

3 participants