-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
118 lines (104 loc) · 3.35 KB
/
server.js
File metadata and controls
118 lines (104 loc) · 3.35 KB
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
const Socket = require("./socket");
const ClientServerBase = require("./clientServerBase");
const decipher = require("./encryption").decrypt;
// ===========================
// Server Class
/**
* dgram udp server used for server to server communication
*/
class Server extends ClientServerBase {
/**
* @param {Object} options - port(default: 41234), bindAddress(default: "0.0.0.0")
*/
constructor({
bindAddress,
port,
encryptionKeys = {},
enforceEncryption = false,
connectionTimeout = 1000,
retryTimeout = 500,
}) {
super({ connectionTimeout, retryTimeout });
this.sockets = {};
this.bindAddress = bindAddress || "0.0.0.0";
this.port = port || 41234;
this.encryptionKeys = encryptionKeys; // used to encrypt/decrypt messages format {[clientID]: key}
this.enforceEncryption = enforceEncryption;
this.server.on("listening", () => {
const address = this.server.address();
console.log(
`Server listening on ${address.address}:${address.port}`
);
});
this.server.bind(port, bindAddress);
}
/**
* emit a message to a socket
* @param {String} topic
* @param {Any} message
* @param {Object} options - type (data (default), keepAlive, ack), guaranteeDelivery (used for guaranteed delivery)
*/
emit(topic, message, options) {
for (const _socket of Object.values(this.sockets)) {
_socket.emit(topic, message, options);
}
}
// =========
// Server Only handlers Handlers
/**
* Setup a connection to client
* @param {*} param0
*/
connect({ data, rinfo, clientID }) {
data &&
!this.sockets[data.socketID] &&
rinfo &&
this.setupSocket({ data, rinfo, clientID });
}
/**
* Setup a new socket
* @param {Object} rinfo
*/
setupSocket({ rinfo, clientID }) {
// ignore connection if encryption is enabled and key is not found
if (this.enforceEncryption && !this.encryptionKeys[clientID]) return;
const _s = new Socket({
port: rinfo.port,
address: rinfo.address,
serverSocket: this.server,
clientID: clientID,
encryptionKey: this.encryptionKeys[clientID],
retryTimeout: this.retryTimeout,
connectionTimeout: this.connectionTimeout,
parentDisconnect: this.disconnect.bind(this),
});
this.sockets[_s.socketID] = _s;
_s.emit("connected", _s.socketID, {
type: "connected",
guaranteeDelivery: true,
});
this.emitLocal("connected", _s);
}
disconnect(socketID) {
delete this.sockets[socketID];
// this.emitLocal("disconnected", socketID);
}
/**
* Server Decryption handling
* @param {*} data
* @param {*} iv
* @param {*} clientID
*/
async decrypt(data, iv, clientID) {
// ignore message if encryption key is not provided
if (clientID && iv && !this.encryptionKeys[clientID]) return;
return await decipher(data, iv, this.encryptionKeys[clientID]);
}
/**
* Return socket based on socket ID
*/
getSocket(socketID) {
return this.sockets[socketID];
}
}
module.exports = Server;