-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
111 lines (94 loc) · 3.19 KB
/
index.js
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
const StreamBuffer = require('./inc/stream_buffer.js');
const dgram = require('dgram');
module.exports = class NodeUdp {
/**
* Creates a new Node UDP socket instance which can be used to send and receive UDP messages.
* When startPort is specified (> -1), the socket will be bound to this port.
* Otherwise bindSocket needs to be called before the socket is actually active.
* @param onResponse - Response handler
* @param {number} startPort - Instantly bind to this port (-1 = to not bind)
* @param {boolean} rebindOnError - Automatically rebind when a socket error occurs?
* @param {number} rebindDelay - Delay before trying to rebind (in milliseconds)
* @param {boolean} littleEndian - Use little endian for numbers (true) or big endian (false)
*/
constructor(onResponse, startPort = -1, rebindOnError = true, rebindDelay = 3000, littleEndian = true) {
this.onResponse = onResponse;
this.rebindOnError = rebindOnError;
this.rebindDelay = rebindDelay;
this.littleEndian = littleEndian;
this.port = 0;
this.isBound = false;
this.udp = dgram.createSocket('udp4');
this.srcAddress = null;
this.srcPort = null;
this.inStream = new StreamBuffer(littleEndian);
this.outStream = new StreamBuffer(littleEndian);
this.udp.on('listening', () => {
this.isBound = true;
const address = this.udp.address();
console.log(`UDP socket listening on ${address.address}:${address.port}`);
});
this.udp.on('error', (err) => {
console.log(`UDP socket error:\n${err.stack}`);
this.udp.close();
this.isBound = false;
if (this.rebindOnError) {
setTimeout(bindSocket(this.port), this.rebindDelay);
} else {
console.log(`UDP socket closed. rebindOnError disabled.`);
}
});
this.udp.on('message', (msg, rinfo) => {
this.inStream.setBuffer(msg);
const length = this.inStream.length();
this.srcAddress = rinfo.address;
this.srcPort = rinfo.port;
onResponse(this.inStream, length, this.srcAddress, this.srcPort);
});
if (startPort > -1) {
this.bindSocket(startPort);
}
}
/**
* Binds the UDP socket to a port.
* When already bound this will close the socket and re-open it.
* @param {number} port - UDP port to bind to (0-65535)
*/
bindSocket(port) {
if (this.isBound)
{
this.udp.close();
this.isBound = false;
}
this.port = port;
console.log(`trying to bind UDP socket ${port}...`);
this.udp.bind(port);
}
/**
* Clears the outgoing buffer.
* This has to be done before writing anything to it.
* When done with writing either call sendResponse or sendResponseTo.
* @param {number} size - max. size of the buffer in bytes
*/
startResponse(size) {
this.outStream.clearBuffer(size);
}
/**
* Sends a response to the source of the last incoming message
*/
sendResponse() {
this.sendResponseTo(this.srcAddress, this.srcPort);
}
/**
* Sends a response to the specified destination
* @param {string} dstAddress - destination address
* @param {number} dstPort - destination port
*/
sendResponseTo(dstAddress, dstPort) {
if (!this.isBound) {
console.error(`UDP socket can't send response. Not bound!`);
return;
}
this.udp.send(this.outStream.buf, 0, this.outStream.offset, dstPort, dstAddress);
}
}