1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
import WebSocket from "ws";
class Client {
constructor(ws) {
this.ws = ws;
this.handlers = {};
ws.on("message", msg => { const d = JSON.parse(msg);
(this.handlers[d.type]||[]).forEach(cb => cb(d.data));
});
const closecb = () =>
(this.handlers["close"]||[]).forEach(cb => cb());
ws.on("close", closecb);
ws.on("error", closecb);
}
on(type, cb) {
(this.handlers[type]||(this.handlers[type]=[])).push(cb);
}
send(type, data) {
this.ws.send(JSON.stringify({type, data}));
}
}
export default class Socket {
constructor(server) {
this.wss = new WebSocket.Server({server});
this.handlers = {};
this.clients = [];
this.wss.on("connection", ws => {
const client = new Client(ws);
this.clients.push(client);
ws.on("message", msg => { const d = JSON.parse(msg);
(this.handlers[d.type]||[]).forEach(cb => cb(client, d.data));
});
let pingTimeout;
const ping = () => { client.send("ping", {});
pingTimeout = setTimeout(() => ws.terminate(), 3e4); };
client.on("pong", () => { clearTimeout(pingTimeout);
setTimeout(ping, 1e3); }); ping();
const closecb = () => {
const i = this.clients.indexOf(client); if (i < 0) return;
(this.handlers["close"]||[]).forEach(cb => cb(client));
this.clients.splice(i, 1);
}
ws.on("close", closecb);
ws.on("error", closecb);
(this.handlers["open"]||[]).forEach(cb => cb(client));
});
}
on(type, cb) {
(this.handlers[type]||(this.handlers[type]=[])).push(cb);
}
sendAll(type, data) {
this.clients.forEach(c => c.send(type, data));
}
};
|