-
Notifications
You must be signed in to change notification settings - Fork 0
/
swarm.ts
121 lines (96 loc) · 2.88 KB
/
swarm.ts
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { EventEmitter } from 'events';
import {inflate} from 'pako';
export enum DecompressionStrategy {
ZlibJson = 'zlib_json',
TextJson = 'text_json'
}
export class SwarmClient extends EventEmitter {
swarmHost: string;
encoding: string;
compression: DecompressionStrategy;
state: string;
socket: WebSocket;
heartbeatInterval: number;
heartbeat: any;
seq: number;
constructor(swarmHost, encoding, compression) {
super();
this.swarmHost = swarmHost || "wss://swarm.hiven.io";
this.encoding = encoding || "json";
this.compression = compression || DecompressionStrategy.ZlibJson;
this.state = "not_connected";
this.socket = null;
this.heartbeatInterval = null;
this.heartbeat = null;
this.seq = 0;
}
connect() {
const socket = new WebSocket(`${this.swarmHost}/socket?encoding=${this.encoding}&compression=${this.compression}`);
if(this.compression === DecompressionStrategy.ZlibJson) {
socket.binaryType = 'arraybuffer';
}
this.socket = socket;
this.state = "connecting";
this.emit("SOCKET_STATE_CHANGE", "connecting");
socket.addEventListener('open', (event) => {
this.state = "tcp_connected";
this.emit("SOCKET_STATE_CHANGE", "tcp_connected");
});
socket.addEventListener('message', (event) => {
const compressed = event.data;
const decompressed = this.decompress(compressed);
this.seq = decompressed.seq;
switch (decompressed.op) {
case 0:
this.emit("HIVEN_EVENT", {type: decompressed.e, data: decompressed.d});
break;
case 1:
this.heartbeatInterval = decompressed.d.hbt_int;
this.startHeartbeating();
this.state = "connected";
this.emit("SOCKET_STATE_CHANGE", "connected");
break;
default:
console.error("Swarm received unknown opcode")
}
});
socket.addEventListener('close', (event) => {
switch(event.code) {
case 4003: {
this.state = event.reason;
this.emit("SOCKET_STATE_CHANGE", event.reason);
}
default: {
this.state = "closed";
this.emit("SOCKET_STATE_CHANGE", "closed");
}
}
});
}
private decompress(data: any): any {
switch (this.compression) {
case DecompressionStrategy.ZlibJson: {
return JSON.parse(inflate(data, {to: 'string'}));
}
default: {
return JSON.parse(data);
}
}
}
sendRaw(data) {
const encoded = JSON.stringify(data);
this.socket.send(encoded);
}
startHeartbeating() {
this.heartbeat = setInterval(() => {
if(this.state !== "connected") {
clearInterval(this.heartbeat);
return;
}
this.sendRaw({"op": 3});
}, this.heartbeatInterval || 30000);
}
identify(token) {
this.sendRaw({"op": 2, "d": {"token": token}});
}
}