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

closing websocket after server received headers but before client.readyState == OPENED causes subsequent connections to hang #27419

Open
binary-person opened this issue Dec 16, 2022 · 0 comments

Comments

@binary-person
Copy link

Description

this issue is related to #15410 and #19123. The timings of the server and browser causes this issue to appear haphazardly and is normally difficult to reproduce reliably.

This is what happens:

  1. client makes a connection to the server
  2. server receives client headers and establishes the connection
  3. client.readyState is still OPENING
  4. closing the websocket during this window of OPENING and OPENED causes the close packet to never be sent
  5. subsequent websocket connections to the same server hang; server never receives those connections

Steps to Reproduce

We first setup the environment to reproduce this bug.

First we setup the server. Paste the following into server.js and run npm install ws and then node server.js

const { WebSocketServer } = require('ws');

const server = new WebSocketServer({ port: 8080 });

server.on('connection', (socket, req) => {
  console.log(req.httpVersion, req.url);
  console.log(req.headers);
  socket.on('message', (data => {
    console.log(data.toString());
    socket.send('received!');
    socket.close();
  }));
  setTimeout(() => {
    if (socket.readyState === socket.OPEN) {
      console.log('timing out, closing');
      socket.close();
    }
  }, 10000);
  socket.on('close', () => {
    console.log('closed');
  });
});

Open Brave, go to http://127.0.0.1:8080, open dev tools, then paste the following into the console

function testLatency() {
  const client = new WebSocket('ws://127.0.0.1:8080/');
  date = Date.now();
  client.onopen = () => {
    console.log(Date.now() - date); client.close();
  };
}

function tryAndBreak(latency = 2) {
  const client = new WebSocket('ws://127.0.0.1:8080/');
  setTimeout(() => {
    console.log(client.readyState);
    client.close();
    console.log(client.readyState);
  }, latency);
}

Now to reproduce this bug:

  1. run testLatency() multiple times. I got 5ms on average
  2. this means we need to choose a delay between 0 and 5ms before we close the websocket. I'll choose 3ms.
  3. run tryAndBreak(3) until two conditions occur (I reproduced this issue on every first try):
  4. this gets printed: WebSocket connection to 'ws://127.0.0.1:8080/' failed: WebSocket is closed before the connection is established.
  5. server receives the connection and prints out client headers BUT does not print "closed"
  6. trying to run testLatency() again will result in the connection hanging. The server also doesn't receive the connection.

Actual result:

On step 3, server never receives the close packet, and subsequent connections hang.

Expected result:

On step 3, server does receive the close packet, and subsequent connections work fine.

Reproduces how often:

Very easy, if you get the timings right.

Brave version (brave://version info)

Brave 1.46.144 Chromium: 108.0.5359.128 (Official Build) (arm64)
Revision 1cd27afdb8e5d057070c0961e04c490d2aca1aa0-refs/branch-heads/5359@{#1185}
OS macOS Version 13.0.1 (Build 22A400)

Version/Channel Information:

  • Can you reproduce this issue with the current release? yes
  • Can you reproduce this issue with the beta channel? N/A didn't test
  • Can you reproduce this issue with the nightly channel? N/A didn't test

Other Additional Information:

  • Does the issue resolve itself when disabling Brave Shields? no
  • Does the issue resolve itself when disabling Brave Rewards? no
  • Is the issue reproducible on the latest version of Chrome? no (even though "WebSocket is closed before the connection is established" gets printed, server still receives the close packet, and following connections work fine)

Miscellaneous Information:

I hope the reproducible steps help facilitate a fix for this issue, since this looks like it has been a problem for more than a year...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant