dns2 2.0.0 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +16 -0
- package/.github/FUNDING.yml +12 -12
- package/.github/workflows/lint.js.yml +17 -0
- package/.github/workflows/node.js.yml +29 -30
- package/LICENSE +18 -18
- package/README.md +227 -196
- package/SECURITY.md +21 -21
- package/client/doh.js +50 -42
- package/client/google.js +27 -27
- package/client/tcp.js +34 -34
- package/client/udp.js +39 -39
- package/example/client/doh.js +12 -12
- package/example/client/google.js +7 -8
- package/example/client/tcp-custom-dns.js +10 -10
- package/example/client/tcp.js +12 -12
- package/example/client/udp-custom-dns.js +11 -11
- package/example/client/udp-default.js +8 -8
- package/example/client/udp-subnet.js +11 -11
- package/example/client/udp.js +8 -8
- package/example/server/dns.js +46 -0
- package/example/server/doh.js +30 -28
- package/example/server/secret.key +28 -28
- package/example/server/server.crt +22 -22
- package/example/server/tcp.js +19 -19
- package/example/server/udp.js +23 -23
- package/index.js +97 -89
- package/lib/reader.js +53 -55
- package/lib/writer.js +42 -42
- package/package.json +42 -34
- package/packet.js +873 -857
- package/server/dns.js +94 -0
- package/server/doh.js +146 -143
- package/server/index.js +31 -24
- package/server/tcp.js +34 -26
- package/server/udp.js +47 -41
- package/test/index.js +395 -244
- package/test/test.js +34 -27
- package/.travis.yml +0 -4
package/server/dns.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const EventEmitter = require('events');
|
|
2
|
+
const DOHServer = require('./doh');
|
|
3
|
+
const TCPServer = require('./tcp');
|
|
4
|
+
const UDPServer = require('./udp');
|
|
5
|
+
|
|
6
|
+
class DNSServer extends EventEmitter {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
super();
|
|
9
|
+
this.servers = {};
|
|
10
|
+
if (options.doh) {
|
|
11
|
+
this.servers.doh = (new DOHServer(options.doh))
|
|
12
|
+
.on('error', error => this.emit('error', error, 'doh'));
|
|
13
|
+
}
|
|
14
|
+
if (options.tcp) {
|
|
15
|
+
this.servers.tcp = (new TCPServer())
|
|
16
|
+
.on('error', error => this.emit('error', error, 'tcp'));
|
|
17
|
+
}
|
|
18
|
+
if (options.udp) {
|
|
19
|
+
this.servers.udp = (new UDPServer(typeof options.udp === 'object' ? options.udp : undefined))
|
|
20
|
+
.on('error', error => this.emit('error', error, 'udp'));
|
|
21
|
+
}
|
|
22
|
+
const servers = Object.values(this.servers);
|
|
23
|
+
this.closed = Promise.all(
|
|
24
|
+
servers.map(server => new Promise(resolve => server.once('close', resolve))),
|
|
25
|
+
).then(() => {
|
|
26
|
+
this.emit('close');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.listening = Promise.all(
|
|
30
|
+
servers.map(server => new Promise(resolve => server.once('listening', resolve))),
|
|
31
|
+
).then(() => {
|
|
32
|
+
const addresses = this.addresses();
|
|
33
|
+
this.emit('listening', addresses);
|
|
34
|
+
return addresses;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const emitRequest = (request, send, client) => this.emit('request', request, send, client);
|
|
38
|
+
const emitRequestError = (error) => this.emit('requestError', error);
|
|
39
|
+
for (const server of servers) {
|
|
40
|
+
server.on('request', emitRequest);
|
|
41
|
+
server.on('requestError', emitRequestError);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (options.handle) {
|
|
45
|
+
this.on('request', options.handle.bind(options));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
addresses() {
|
|
50
|
+
const addresses = {};
|
|
51
|
+
const { udp, tcp, doh } = this.servers;
|
|
52
|
+
if (udp) {
|
|
53
|
+
addresses.udp = udp.address();
|
|
54
|
+
}
|
|
55
|
+
if (tcp) {
|
|
56
|
+
addresses.tcp = tcp.address();
|
|
57
|
+
}
|
|
58
|
+
if (doh) {
|
|
59
|
+
addresses.doh = doh.address();
|
|
60
|
+
}
|
|
61
|
+
return addresses;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
listen(options = {}) {
|
|
65
|
+
for (const serverType of Object.keys(this.servers)) {
|
|
66
|
+
const server = this.servers[serverType];
|
|
67
|
+
const serverOptions = options[serverType]; // Port or { port, address }
|
|
68
|
+
|
|
69
|
+
if (serverOptions && serverOptions.port) {
|
|
70
|
+
server.listen(serverOptions.port, serverOptions.address);
|
|
71
|
+
} else {
|
|
72
|
+
server.listen(serverOptions);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return this.listening;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
close() {
|
|
80
|
+
const { doh, udp, tcp } = this.servers;
|
|
81
|
+
if (udp) {
|
|
82
|
+
udp.close();
|
|
83
|
+
}
|
|
84
|
+
if (tcp) {
|
|
85
|
+
tcp.close();
|
|
86
|
+
}
|
|
87
|
+
if (doh) {
|
|
88
|
+
doh.close();
|
|
89
|
+
}
|
|
90
|
+
return this.closed;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = DNSServer;
|
package/server/doh.js
CHANGED
|
@@ -1,143 +1,146 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const https = require('https');
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const EventEmitter = require(
|
|
6
|
-
const
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const { URL } = require('url');
|
|
4
|
+
const Packet = require('../packet');
|
|
5
|
+
const EventEmitter = require('events');
|
|
6
|
+
const { debuglog } = require('util');
|
|
7
|
+
|
|
8
|
+
const debug = debuglog('dns2-server');
|
|
9
|
+
|
|
10
|
+
const decodeBase64URL = str => {
|
|
11
|
+
let queryData = str
|
|
12
|
+
.replace(/-/g, '+')
|
|
13
|
+
.replace(/_/g, '/');
|
|
14
|
+
const pad = queryData.length % 4;
|
|
15
|
+
if (pad === 1) return;
|
|
16
|
+
if (pad) {
|
|
17
|
+
queryData += new Array(5 - pad).join('=');
|
|
18
|
+
}
|
|
19
|
+
return queryData;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const readStream = stream => new Promise((resolve, reject) => {
|
|
23
|
+
let buffer = '';
|
|
24
|
+
stream
|
|
25
|
+
.on('error', reject)
|
|
26
|
+
.on('data', chunk => { buffer += chunk; })
|
|
27
|
+
.on('end', () => resolve(buffer));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
class Server extends EventEmitter {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
super();
|
|
33
|
+
const { ssl } = Object.assign(this, { cors: true }, options);
|
|
34
|
+
this.server = (ssl ? https.createServer(options) : http.createServer())
|
|
35
|
+
.on('request', this.handleRequest.bind(this))
|
|
36
|
+
.on('listening', () => this.emit('listening', this.address()))
|
|
37
|
+
.on('error', error => this.emit('error', error))
|
|
38
|
+
.on('close', () => {
|
|
39
|
+
this.server.removeAllListeners();
|
|
40
|
+
this.emit('close');
|
|
41
|
+
});
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async handleRequest(client, res) {
|
|
46
|
+
try {
|
|
47
|
+
const { method, url, headers } = client;
|
|
48
|
+
const { pathname, searchParams: query } = new URL(url, 'http://unused/');
|
|
49
|
+
const { cors } = this;
|
|
50
|
+
if (cors === true) {
|
|
51
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
52
|
+
} else if (typeof cors === 'string') {
|
|
53
|
+
res.setHeader('Access-Control-Allow-Origin', cors);
|
|
54
|
+
res.setHeader('Vary', 'Origin');
|
|
55
|
+
} else if (typeof cors === 'function') {
|
|
56
|
+
const isAllowed = cors(headers.origin);
|
|
57
|
+
res.setHeader('Access-Control-Allow-Origin', isAllowed ? headers.origin : 'false');
|
|
58
|
+
res.setHeader('Vary', 'Origin');
|
|
59
|
+
}
|
|
60
|
+
// debug
|
|
61
|
+
debug('request', method, url);
|
|
62
|
+
// We are only handling get and post as reqired by rfc
|
|
63
|
+
if ((method !== 'GET' && method !== 'POST')) {
|
|
64
|
+
res.writeHead(405, { 'Content-Type': 'text/plain' });
|
|
65
|
+
res.write('405 Method not allowed\n');
|
|
66
|
+
res.end();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Check so the uri is correct
|
|
70
|
+
if (pathname !== '/dns-query') {
|
|
71
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
72
|
+
res.write('404 Not Found\n');
|
|
73
|
+
res.end();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Make sure the requestee is requesting the correct content type
|
|
77
|
+
const contentType = headers.accept;
|
|
78
|
+
if (contentType !== 'application/dns-message') {
|
|
79
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
80
|
+
res.write('400 Bad Request: Illegal content type\n');
|
|
81
|
+
res.end();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
let queryData;
|
|
85
|
+
if (method === 'GET') {
|
|
86
|
+
// Parse query string for the request data
|
|
87
|
+
const dns = query.get('dns');
|
|
88
|
+
if (!dns) {
|
|
89
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
90
|
+
res.write('400 Bad Request: No query defined\n');
|
|
91
|
+
res.end();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Decode from Base64Url Encoding
|
|
95
|
+
const base64 = decodeBase64URL(dns);
|
|
96
|
+
if (!base64) {
|
|
97
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
98
|
+
res.write('400 Bad Request: Invalid query data\n');
|
|
99
|
+
res.end();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Decode Base64 to buffer
|
|
103
|
+
queryData = Buffer.from(base64, 'base64');
|
|
104
|
+
} else if (method === 'POST') {
|
|
105
|
+
queryData = await readStream(client);
|
|
106
|
+
}
|
|
107
|
+
// Parse DNS query and Raise event.
|
|
108
|
+
const message = Packet.parse(queryData);
|
|
109
|
+
this.emit('request', message, this.response.bind(this, res), client);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
this.emit('requestError', e);
|
|
112
|
+
res.destroy();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Send of the response to the client
|
|
118
|
+
* @param {*} res
|
|
119
|
+
* @param {*} message
|
|
120
|
+
*/
|
|
121
|
+
response(res, message) {
|
|
122
|
+
debug('response');
|
|
123
|
+
res.setHeader('Content-Type', 'application/dns-message');
|
|
124
|
+
res.writeHead(200);
|
|
125
|
+
res.end(message.toBuffer());
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* listen
|
|
130
|
+
* @param {*} port
|
|
131
|
+
* @returns
|
|
132
|
+
*/
|
|
133
|
+
listen(port, address) {
|
|
134
|
+
return this.server.listen(port || this.port, address);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
address() {
|
|
138
|
+
return this.server.address();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
close() {
|
|
142
|
+
return this.server.close();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = Server;
|
package/server/index.js
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
const UDPServer = require('./udp');
|
|
2
|
-
const TCPServer = require('./tcp');
|
|
3
|
-
const DOHServer = require('./doh');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
const UDPServer = require('./udp');
|
|
2
|
+
const TCPServer = require('./tcp');
|
|
3
|
+
const DOHServer = require('./doh');
|
|
4
|
+
const DNSServer = require('./dns');
|
|
5
|
+
|
|
6
|
+
const createUDPServer = options => {
|
|
7
|
+
return new UDPServer(options);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const createTCPServer = options => {
|
|
11
|
+
return new TCPServer(options);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const createDOHServer = options => {
|
|
15
|
+
return new DOHServer(options);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const createServer = options => {
|
|
19
|
+
return new DNSServer(options);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
UDPServer,
|
|
24
|
+
TCPServer,
|
|
25
|
+
DOHServer,
|
|
26
|
+
DNSServer,
|
|
27
|
+
createTCPServer,
|
|
28
|
+
createUDPServer,
|
|
29
|
+
createDOHServer,
|
|
30
|
+
createServer,
|
|
31
|
+
};
|
package/server/tcp.js
CHANGED
|
@@ -1,26 +1,34 @@
|
|
|
1
|
-
const tcp = require('net');
|
|
2
|
-
const Packet = require('../packet');
|
|
3
|
-
|
|
4
|
-
class Server extends tcp.Server {
|
|
5
|
-
constructor(options) {
|
|
6
|
-
super();
|
|
7
|
-
if (typeof options === 'function') {
|
|
8
|
-
this.on('request', options);
|
|
9
|
-
}
|
|
10
|
-
this.on('connection', this.handle.bind(this));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
const tcp = require('net');
|
|
2
|
+
const Packet = require('../packet');
|
|
3
|
+
|
|
4
|
+
class Server extends tcp.Server {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super();
|
|
7
|
+
if (typeof options === 'function') {
|
|
8
|
+
this.on('request', options);
|
|
9
|
+
}
|
|
10
|
+
this.on('connection', this.handle.bind(this));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async handle(client) {
|
|
14
|
+
try {
|
|
15
|
+
const data = await Packet.readStream(client);
|
|
16
|
+
const message = Packet.parse(data);
|
|
17
|
+
this.emit('request', message, this.response.bind(this, client), client);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
this.emit('requestError', e);
|
|
20
|
+
client.destroy();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
response(client, message) {
|
|
25
|
+
if (message instanceof Packet) {
|
|
26
|
+
message = message.toBuffer();
|
|
27
|
+
}
|
|
28
|
+
const len = Buffer.alloc(2);
|
|
29
|
+
len.writeUInt16BE(message.length);
|
|
30
|
+
client.end(Buffer.concat([ len, message ]));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = Server;
|
package/server/udp.js
CHANGED
|
@@ -1,41 +1,47 @@
|
|
|
1
|
-
const udp = require('dgram');
|
|
2
|
-
const Packet = require('../packet');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* [Server description]
|
|
6
|
-
* @docs https://tools.ietf.org/html/rfc1034
|
|
7
|
-
* @docs https://tools.ietf.org/html/rfc1035
|
|
8
|
-
*/
|
|
9
|
-
class Server extends udp.Socket {
|
|
10
|
-
constructor(options) {
|
|
11
|
-
let type = 'udp4';
|
|
12
|
-
if (typeof options === 'object') {
|
|
13
|
-
type = options.type;
|
|
14
|
-
}
|
|
15
|
-
super(type);
|
|
16
|
-
if (typeof options === 'function') {
|
|
17
|
-
this.on('request', options);
|
|
18
|
-
}
|
|
19
|
-
this.on('message', this.handle.bind(this));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
const udp = require('dgram');
|
|
2
|
+
const Packet = require('../packet');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* [Server description]
|
|
6
|
+
* @docs https://tools.ietf.org/html/rfc1034
|
|
7
|
+
* @docs https://tools.ietf.org/html/rfc1035
|
|
8
|
+
*/
|
|
9
|
+
class Server extends udp.Socket {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
let type = 'udp4';
|
|
12
|
+
if (typeof options === 'object') {
|
|
13
|
+
type = options.type;
|
|
14
|
+
}
|
|
15
|
+
super(type);
|
|
16
|
+
if (typeof options === 'function') {
|
|
17
|
+
this.on('request', options);
|
|
18
|
+
}
|
|
19
|
+
this.on('message', this.handle.bind(this));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
handle(data, rinfo) {
|
|
23
|
+
try {
|
|
24
|
+
const message = Packet.parse(data);
|
|
25
|
+
this.emit('request', message, this.response.bind(this, rinfo), rinfo);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
this.emit('requestError', e);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
response(rinfo, message) {
|
|
32
|
+
if (message instanceof Packet) { message = message.toBuffer(); }
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
this.send(message, rinfo.port, rinfo.address, err => {
|
|
35
|
+
if (err) return reject(err);
|
|
36
|
+
resolve(message);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
listen(port, address) {
|
|
42
|
+
return new Promise(resolve =>
|
|
43
|
+
this.bind(port, address, resolve));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = Server;
|