Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/resources/scripts/plugins/Websocket.ts
7458 views
1
import Sockette from 'sockette';
2
import { EventEmitter } from 'events';
3
4
export class Websocket extends EventEmitter {
5
// Timer instance for this socket.
6
private timer: any = null;
7
8
// The backoff for the timer, in milliseconds.
9
private backoff = 5000;
10
11
// The socket instance being tracked.
12
private socket: Sockette | null = null;
13
14
// The URL being connected to for the socket.
15
private url: string | null = null;
16
17
// The authentication token passed along with every request to the Daemon.
18
// By default this token expires every 15 minutes and must therefore be
19
// refreshed at a pretty continuous interval. The socket server will respond
20
// with "token expiring" and "token expired" events when approaching 3 minutes
21
// and 0 minutes to expiry.
22
private token = '';
23
24
// Connects to the websocket instance and sets the token for the initial request.
25
connect(url: string): this {
26
this.url = url;
27
28
this.socket = new Sockette(`${this.url}`, {
29
onmessage: (e) => {
30
try {
31
const { event, args } = JSON.parse(e.data);
32
args ? this.emit(event, ...args) : this.emit(event);
33
} catch (ex) {
34
console.warn('Failed to parse incoming websocket message.', ex);
35
}
36
},
37
onopen: () => {
38
// Clear the timers, we managed to connect just fine.
39
this.timer && clearTimeout(this.timer);
40
this.backoff = 5000;
41
42
this.emit('SOCKET_OPEN');
43
this.authenticate();
44
},
45
onreconnect: () => {
46
this.emit('SOCKET_RECONNECT');
47
this.authenticate();
48
},
49
onclose: () => this.emit('SOCKET_CLOSE'),
50
onerror: (error) => this.emit('SOCKET_ERROR', error),
51
});
52
53
this.timer = setTimeout(() => {
54
this.backoff = this.backoff + 2500 >= 20000 ? 20000 : this.backoff + 2500;
55
this.socket && this.socket.close();
56
clearTimeout(this.timer);
57
58
// Re-attempt connecting to the socket.
59
this.connect(url);
60
}, this.backoff);
61
62
return this;
63
}
64
65
// Sets the authentication token to use when sending commands back and forth
66
// between the websocket instance.
67
setToken(token: string, isUpdate = false): this {
68
this.token = token;
69
70
if (isUpdate) {
71
this.authenticate();
72
}
73
74
return this;
75
}
76
77
authenticate() {
78
if (this.url && this.token) {
79
this.send('auth', this.token);
80
}
81
}
82
83
close(code?: number, reason?: string) {
84
this.url = null;
85
this.token = '';
86
this.socket && this.socket.close(code, reason);
87
}
88
89
open() {
90
this.socket && this.socket.open();
91
}
92
93
reconnect() {
94
this.socket && this.socket.reconnect();
95
}
96
97
send(event: string, payload?: string | string[]) {
98
this.socket &&
99
this.socket.send(
100
JSON.stringify({
101
event,
102
args: Array.isArray(payload) ? payload : [payload],
103
})
104
);
105
}
106
}
107
108