mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
Replace socket.io with plain WebSocket
Replace socket.io with plain WebSocket using the ws library as it doesn't really provide any useful tools over plain WebSocket when it comes to implementing reliable communication that works across reconnects. The widespread browser support for WebSocket also means it has little value to add for the web interface over WebSocket.
This commit is contained in:
1 parent
808bd6b453
commit
677512512e
12 files changed
+139
-149
No files matched your search
+31
-48
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const events = require("events");
|
||||
const io = require("socket.io-client");
|
||||
const WebSocket = require("ws");
|
||||
|
||||
const schema = require("lib/schema");
|
||||
|
||||
@@ -8,12 +8,11 @@ const schema = require("lib/schema");
|
||||
/**
|
||||
* Connector for master server clients
|
||||
*/
|
||||
class SocketIOClientConnector extends events.EventEmitter {
|
||||
constructor(url, token) {
|
||||
class WebSocketClientConnector extends events.EventEmitter {
|
||||
constructor(url) {
|
||||
super();
|
||||
|
||||
this._url = url;
|
||||
this._token = token;
|
||||
|
||||
this._seq = 1;
|
||||
this._state = "new";
|
||||
@@ -33,7 +32,7 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
* @returns the sequence number of the message sent
|
||||
*/
|
||||
send(type, data) {
|
||||
this._socket.send({ seq: this._seq, type, data });
|
||||
this._socket.send(JSON.stringify({ seq: this._seq, type, data }));
|
||||
return this._seq++;
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
*/
|
||||
close(reason) {
|
||||
this.send('close', { reason });
|
||||
this.disconnect();
|
||||
this._socket.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,19 +53,13 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
this._check(["new"]);
|
||||
this._state = "handshake";
|
||||
|
||||
// Open socket.io connection to master
|
||||
console.log(`SOCKET | connecting to ${this._url}`)
|
||||
let url = new URL(this._url);
|
||||
url.searchParams.append('token', this._token);
|
||||
url.pathname += "api/socket";
|
||||
|
||||
// I really have to question the choice of having the path connected
|
||||
// to be passed as separate parameter instead of the namespace.
|
||||
let urlPath = url.pathname + "socket.io";
|
||||
url.pathname = "";
|
||||
this._socket = io(url.href, {
|
||||
path: urlPath,
|
||||
reconnectionAttempts: 2,
|
||||
// Open WebSocket to master
|
||||
console.log(`SOCKET | connecting to ${url}`)
|
||||
|
||||
this._socket = new WebSocket(url, {
|
||||
// For now we do not verify TLS certificates since the default setup is
|
||||
// to create a self-signed certificate.
|
||||
rejectUnauthorized: false,
|
||||
@@ -79,45 +72,35 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
}
|
||||
|
||||
_attachSocketHandlers() {
|
||||
this._socket.on("close", (code, reason) => {
|
||||
console.log(`SOCKET | Close (code: ${code}, reason: ${reason})`);
|
||||
});
|
||||
this._socket.on("error", err => {
|
||||
console.error("SOCKET | Error:", err);
|
||||
this._socket.close();
|
||||
});
|
||||
this._socket.on("unexpected-response", (req, res) => {
|
||||
let data = "";
|
||||
res.on('data', (chunk) => { data += chunk; });
|
||||
res.on('end', () => {
|
||||
console.error(`SOCKET | Unexpeced Response ${res.statusCode}`);
|
||||
console.error(data);
|
||||
});
|
||||
});
|
||||
|
||||
/*this._socket.on("connect_error", err => {
|
||||
console.log("SOCKET | Connect error:", err);
|
||||
});*/
|
||||
this._socket.on("connect_timeout", () => {
|
||||
console.log("SOCKET | Connect timeout");
|
||||
this._socket.on("open", () => {
|
||||
console.log("SOCKET | Open");
|
||||
});
|
||||
this._socket.on("reconnect", attempt => {
|
||||
console.log(`SOCKET | Reconnect no. ${attempt} succeeded`);
|
||||
this._socket.on("ping", data => {
|
||||
console.log(`SOCKET | Ping (data: ${data}`);
|
||||
});
|
||||
this._socket.on("reconnect_attempt", () => {
|
||||
console.log("SOCKET | Attempting reconnect");
|
||||
});
|
||||
this._socket.on("reconnecting", attempt => {
|
||||
console.log(`SOCKET | Attempting reconnect no. ${attempt}`);
|
||||
});
|
||||
/*this._socket.on("reconnect_error", err => {
|
||||
console.log("SOCKET | Reconnect error:", err);
|
||||
});*/
|
||||
this._socket.on("reconnect_failed", () => {
|
||||
console.log("SOCKET | Reconnecting failed");
|
||||
});
|
||||
/*this._socket.on("ping", () => {
|
||||
console.log("SOCKET | Ping");
|
||||
});
|
||||
this._socket.on("pong", (ms) => {
|
||||
// XXX Latency might be useful
|
||||
console.log(`SOCKET | Pong latency ${ms}ms`);
|
||||
});*/
|
||||
this._socket.on("connect", () => {
|
||||
console.log("SOCKET | connected");
|
||||
this._socket.on("pong", data => {
|
||||
console.log(`SOCKET | Pong (data: ${data}`);
|
||||
});
|
||||
|
||||
// Handle messages
|
||||
this._socket.on("message", message => {
|
||||
this._socket.on("message", data => {
|
||||
let message = JSON.parse(data);
|
||||
if (this._state === "handshake") {
|
||||
this._processHandshake(message);
|
||||
} else if (this._state === "ready") {
|
||||
@@ -132,7 +115,7 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
* Immediatly close the connection
|
||||
*/
|
||||
disconnect() {
|
||||
this._socket.close();
|
||||
this._socket.terminate();
|
||||
}
|
||||
|
||||
_processHandshake(message) {
|
||||
@@ -155,7 +138,7 @@ class SocketIOClientConnector extends events.EventEmitter {
|
||||
} else if (type === 'close') {
|
||||
console.log(`SOCKET | received close from server: ${data.reason}`);
|
||||
this.emit('error', new Error(`server closed during handshake: ${data.reason}`));
|
||||
this._socket.close();
|
||||
this._socket.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +207,6 @@ class VirtualConnector extends events.EventEmitter {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SocketIOClientConnector,
|
||||
WebSocketClientConnector,
|
||||
VirtualConnector,
|
||||
};
|
||||
@@ -87,10 +87,6 @@ let downloadList = [
|
||||
url: "https://fonts.googleapis.com/css?family=Roboto",
|
||||
file: "static/external/css/Roboto.css",
|
||||
},
|
||||
{
|
||||
url: "https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js",
|
||||
file: "static/external/socket.io.js",
|
||||
},
|
||||
]
|
||||
|
||||
// initiate folder creations and downloads
|
||||
|
||||
+4
-2
@@ -105,8 +105,9 @@ const clientHandshake = ajv.compile({
|
||||
"type": { const: "register_slave" },
|
||||
"data": {
|
||||
additionalProperties: false,
|
||||
required: ["agent", "version", "name", "id"],
|
||||
required: ["token", "agent", "version", "name", "id"],
|
||||
properties: {
|
||||
"token": { type: "string" },
|
||||
"agent": { type: "string" },
|
||||
"version": { type: "string" },
|
||||
"name": { type: "string" },
|
||||
@@ -120,8 +121,9 @@ const clientHandshake = ajv.compile({
|
||||
"type": { const: "register_control" },
|
||||
"data": {
|
||||
additionalProperties: false,
|
||||
required: ["agent", "version"],
|
||||
required: ["token", "agent", "version"],
|
||||
properties: {
|
||||
"token": { type: "string" },
|
||||
"agent": { type: "string" },
|
||||
"version": { type: "string" },
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user