liamcottle / rustplus.js

Unofficial NodeJS library for controlling Smart Switches in the PC game Rust
224 stars 46 forks source link

Parse Error: Expected HTTP/ #49

Closed kamrote closed 1 year ago

kamrote commented 1 year ago

Seems that some specific servers have issues w/ connecting, in this particular case this issue was on rusticated us main

Error: Parse Error: Expected HTTP/
    at Socket.socketOnData (node:_http_client:534:22)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:324:12)
    at readableAddChunk (node:internal/streams/readable:297:9)
    at Readable.push (node:internal/streams/readable:234:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
Emitted 'error' event on RustPlus instance at:
    at WebSocket.<anonymous> (C:\Users\kamrote\Documents\GitHub\bot\node_modules\@liamcottle\rustplus.js\rustplus.js:71:22)
    at WebSocket.emit (node:events:513:28)
    at emitErrorAndClose (C:\Users\kamrote\Documents\GitHub\bot\node_modules\ws\lib\websocket.js:1002:13)
    at ClientRequest.<anonymous> (C:\Users\kamrote\Documents\GitHub\bot\node_modules\ws\lib\websocket.js:854:5)
    at ClientRequest.emit (node:events:513:28)
    at Socket.socketOnData (node:_http_client:543:9)
    at Socket.emit (node:events:513:28)
    [... lines matching original stack trace ...]
    at Readable.push (node:internal/streams/readable:234:10) {
  bytesParsed: 0,
  code: 'HPE_INVALID_CONSTANT',
  reason: 'Expected HTTP/',
  rawPacket: Buffer(4) [Uint8Array] [ 136, 2, 3, 232 ]
}
kamrote commented 1 year ago

seems that this issue is caused by some servers purposefully blocking the IP of servers/vpns/proxies, can only really fix by buying a residential proxy or running on a local machine

liamcottle commented 1 year ago

Thanks for the update! Linking this with issue #14 for future reference.

s8wa2 commented 7 months ago

Some additional info for anyone finding this in the future:

This is caused by a premature socket.Close() in the CompanionServer.Listener class inside the Assembly-CSharp.dll from the server game files. Here is the code that causes it:

this._server.Start((Action<IWebSocketConnection>) (socket =>
      {
        IPAddress address = socket.ConnectionInfo.ClientIpAddress;
        if (!listener.Limiter.TryAdd(address) || listener._ipBans.IsBanned(address))
        {
          socket.Close();
        }
        else
        {
          Connection conn = new Connection(Interlocked.Increment(ref listener._nextConnectionId), listener, socket);
          socket.OnClose = (Action) (() =>
          {
            listener.Limiter.Remove(address);
            syncContext.Post((SendOrPostCallback) (c => ((Connection) c).OnClose()), (object) conn);
          });
          socket.OnBinary = new BinaryDataHandler(conn.OnMessage);
          socket.OnError = new Action<Exception>(UnityEngine.Debug.LogError);
        }
      }));

Normally, the websocket would be upgraded after the initial request, then after the handshake is complete, it would send the close packet. However, rust+ sends this prematurely, in the reply packet to the websocket initiation request, rather than after the upgrade handshake is complete. Because the ws library is expecting a reply like HTTP/1.1 101 Switching Protocols, it errors when it receives the byte sequence 0x88, 0x02, 0x03, 0xE8 (websocket close w/ optional status code of 1000 - normal closure) see RFC 6455.

Here's partial list of what can cause rust+ to call socket.Close() early:

Normal websocket handshake: normal-ws

Rust+ premature close (highlighted frame = websocket close): rust-ws