aedes 0.51.3 → 1.0.0
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/.github/actions/sticky-pr-comment/action.yml +55 -0
- package/.github/workflows/benchmark-compare-serial.yml +60 -0
- package/.github/workflows/ci.yml +12 -17
- package/.release-it.json +18 -0
- package/.taprc +15 -6
- package/README.md +6 -4
- package/aedes.d.ts +0 -6
- package/aedes.js +270 -242
- package/benchmarks/README.md +33 -0
- package/benchmarks/pingpong.js +94 -25
- package/benchmarks/receiver.js +77 -0
- package/benchmarks/report.js +150 -0
- package/benchmarks/runBenchmarks.js +118 -0
- package/benchmarks/sender.js +86 -0
- package/benchmarks/server.js +19 -18
- package/checkVersion.js +20 -0
- package/docs/Aedes.md +66 -8
- package/docs/Client.md +3 -4
- package/docs/Examples.md +39 -22
- package/docs/MIGRATION.md +50 -0
- package/eslint.config.js +8 -0
- package/example.js +51 -40
- package/examples/clusters/index.js +28 -23
- package/examples/clusters/package.json +10 -6
- package/lib/client.js +405 -306
- package/lib/handlers/connect.js +42 -38
- package/lib/handlers/index.js +9 -11
- package/lib/handlers/ping.js +2 -3
- package/lib/handlers/puback.js +5 -5
- package/lib/handlers/publish.js +29 -14
- package/lib/handlers/pubrec.js +9 -17
- package/lib/handlers/pubrel.js +34 -25
- package/lib/handlers/subscribe.js +47 -43
- package/lib/handlers/unsubscribe.js +16 -19
- package/lib/qos-packet.js +14 -17
- package/lib/utils.js +5 -12
- package/lib/write.js +4 -5
- package/package.json +134 -136
- package/test/auth.js +468 -804
- package/test/basic.js +613 -575
- package/test/bridge.js +44 -40
- package/test/client-pub-sub.js +531 -504
- package/test/close_socket_by_other_party.js +137 -102
- package/test/connect.js +487 -484
- package/test/drain-timeout.js +593 -0
- package/test/drain-toxiproxy.js +620 -0
- package/test/events.js +173 -145
- package/test/helper.js +351 -73
- package/test/keep-alive.js +40 -67
- package/test/meta.js +257 -210
- package/test/not-blocking.js +93 -197
- package/test/qos1.js +464 -554
- package/test/qos2.js +308 -393
- package/test/regr-21.js +39 -21
- package/test/require.cjs +22 -0
- package/test/retain.js +349 -398
- package/test/topics.js +176 -183
- package/test/types/aedes.test-d.ts +4 -8
- package/test/will.js +310 -428
- package/types/instance.d.ts +40 -35
- package/types/packet.d.ts +10 -10
- package/.coveralls.yml +0 -1
- package/benchmarks/bombing.js +0 -34
- package/benchmarks/bombingQoS1.js +0 -36
- package/benchmarks/throughputCounter.js +0 -23
- package/benchmarks/throughputCounterQoS1.js +0 -33
- package/types/.eslintrc.json +0 -47
package/test/auth.js
CHANGED
|
@@ -1,430 +1,151 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
t.
|
|
18
|
-
t.equal(username, 'my username', 'username is there')
|
|
19
|
-
t.
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { once } from 'node:events'
|
|
3
|
+
import Client from '../lib/client.js'
|
|
4
|
+
import {
|
|
5
|
+
connect,
|
|
6
|
+
createAndConnect,
|
|
7
|
+
nextPacket,
|
|
8
|
+
nextPacketWithTimeOut,
|
|
9
|
+
setup,
|
|
10
|
+
subscribe,
|
|
11
|
+
subscribeMultiple,
|
|
12
|
+
} from './helper.js'
|
|
13
|
+
import { Aedes } from '../aedes.js'
|
|
14
|
+
|
|
15
|
+
async function testAuthenticationError (t, errObject, expectedReturnCode) {
|
|
16
|
+
const authenticate = (client, username, password, cb) => {
|
|
17
|
+
t.assert.equal(client instanceof Client, true, 'client is there')
|
|
18
|
+
t.assert.equal(username, 'my username', 'username is there')
|
|
19
|
+
t.assert.equal(password.toString(), 'my pass', 'password is there')
|
|
20
|
+
cb(errObject, null)
|
|
21
|
+
}
|
|
22
|
+
const broker = await Aedes.createBroker({ authenticate })
|
|
23
|
+
t.after(() => broker.close())
|
|
24
|
+
broker.on('clientReady', (client) => {
|
|
25
|
+
throw new Error('client should not ready')
|
|
26
|
+
})
|
|
27
|
+
const packet = await connect(setup(broker), { verifyReturnedOk: false })
|
|
28
|
+
t.assert.deepEqual(structuredClone(packet), {
|
|
29
|
+
cmd: 'connack',
|
|
30
|
+
returnCode: expectedReturnCode,
|
|
31
|
+
length: 2,
|
|
32
|
+
qos: 0,
|
|
33
|
+
retain: false,
|
|
34
|
+
dup: false,
|
|
35
|
+
topic: null,
|
|
36
|
+
payload: null,
|
|
37
|
+
sessionPresent: false
|
|
38
|
+
}, 'unsuccessful connack, unauthorized')
|
|
39
|
+
const [client, err] = await once(broker, 'clientError')
|
|
40
|
+
t.assert.equal(client.id, 'my-client')
|
|
41
|
+
t.assert.equal(err.errorCode, expectedReturnCode)
|
|
42
|
+
t.assert.equal(err.message, 'Auth error')
|
|
43
|
+
t.assert.equal(broker.connectedClients, 0, 'no connected clients')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test('authenticate successfully a client with username and password', async (t) => {
|
|
47
|
+
t.plan(5)
|
|
48
|
+
const authenticate = (client, username, password, cb) => {
|
|
49
|
+
t.assert.equal(client instanceof Client, true, 'client is there')
|
|
50
|
+
t.assert.equal(username, 'my username', 'username is there')
|
|
51
|
+
t.assert.equal(password.toString(), 'my pass', 'password is there')
|
|
20
52
|
cb(null, true)
|
|
21
53
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
qos: 0,
|
|
40
|
-
retain: false,
|
|
41
|
-
dup: false,
|
|
42
|
-
topic: null,
|
|
43
|
-
payload: null,
|
|
44
|
-
sessionPresent: false
|
|
45
|
-
}, 'successful connack')
|
|
46
|
-
})
|
|
54
|
+
const broker = await Aedes.createBroker()
|
|
55
|
+
// explicitly override authenticate instead of passing it as a parameter
|
|
56
|
+
broker.authenticate = authenticate
|
|
57
|
+
t.after(() => broker.close())
|
|
58
|
+
const packet = await connect(setup(broker))
|
|
59
|
+
t.assert.deepEqual(structuredClone(packet), {
|
|
60
|
+
cmd: 'connack',
|
|
61
|
+
returnCode: 0,
|
|
62
|
+
length: 2,
|
|
63
|
+
qos: 0,
|
|
64
|
+
retain: false,
|
|
65
|
+
dup: false,
|
|
66
|
+
topic: null,
|
|
67
|
+
payload: null,
|
|
68
|
+
sessionPresent: false
|
|
69
|
+
}, 'successful connack')
|
|
70
|
+
t.assert.equal(broker.connectedClients, 1, 'one connected client')
|
|
47
71
|
})
|
|
48
72
|
|
|
49
|
-
test('authenticate unsuccessfully a client with username and password',
|
|
50
|
-
t.plan(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
56
|
-
t.type(client, Client, 'client is there')
|
|
57
|
-
t.equal(username, 'my username', 'username is there')
|
|
58
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
73
|
+
test('authenticate unsuccessfully a client with username and password', async (t) => {
|
|
74
|
+
t.plan(7)
|
|
75
|
+
const authenticate = (client, username, password, cb) => {
|
|
76
|
+
t.assert.equal(client instanceof Client, true, 'client is there')
|
|
77
|
+
t.assert.equal(username, 'my username', 'username is there')
|
|
78
|
+
t.assert.equal(password.toString(), 'my pass', 'password is there')
|
|
59
79
|
cb(null, false)
|
|
60
80
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
s.broker.on('clientReady', function (client) {
|
|
67
|
-
t.fail('client should not ready')
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
s.outStream.on('data', function (packet) {
|
|
71
|
-
t.same(packet, {
|
|
72
|
-
cmd: 'connack',
|
|
73
|
-
returnCode: 5,
|
|
74
|
-
length: 2,
|
|
75
|
-
qos: 0,
|
|
76
|
-
retain: false,
|
|
77
|
-
dup: false,
|
|
78
|
-
topic: null,
|
|
79
|
-
payload: null,
|
|
80
|
-
sessionPresent: false
|
|
81
|
-
}, 'unsuccessful connack, unauthorized')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
eos(s.outStream, function () {
|
|
85
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
81
|
+
const broker = await Aedes.createBroker({ authenticate })
|
|
82
|
+
t.after(() => broker.close())
|
|
83
|
+
broker.on('clientReady', (client) => {
|
|
84
|
+
throw new Error('client should not ready')
|
|
86
85
|
})
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
const packet = await connect(setup(broker), { verifyReturnedOk: false })
|
|
88
|
+
t.assert.deepEqual(structuredClone(packet), {
|
|
89
|
+
cmd: 'connack',
|
|
90
|
+
returnCode: 5,
|
|
91
|
+
length: 2,
|
|
92
|
+
qos: 0,
|
|
93
|
+
retain: false,
|
|
94
|
+
dup: false,
|
|
95
|
+
topic: null,
|
|
96
|
+
payload: null,
|
|
97
|
+
sessionPresent: false
|
|
98
|
+
})
|
|
99
|
+
const [client, err] = await once(broker, 'clientError')
|
|
100
|
+
t.assert.equal(client.id, 'my-client')
|
|
101
|
+
t.assert.equal(err.errorCode, 5)
|
|
102
|
+
t.assert.equal(broker.connectedClients, 0, 'no connected clients')
|
|
98
103
|
})
|
|
99
104
|
|
|
100
|
-
test('authenticate errors',
|
|
101
|
-
t.plan(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
t
|
|
105
|
-
|
|
106
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
107
|
-
t.type(client, Client, 'client is there')
|
|
108
|
-
t.equal(username, 'my username', 'username is there')
|
|
109
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
110
|
-
cb(new Error('this should happen!'))
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
s.broker.on('clientError', function (client, err) {
|
|
114
|
-
t.equal(err.message, 'this should happen!')
|
|
115
|
-
t.equal(err.errorCode, 5)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
s.broker.on('clientReady', function (client) {
|
|
119
|
-
t.fail('client should not ready')
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
s.outStream.on('data', function (packet) {
|
|
123
|
-
t.same(packet, {
|
|
124
|
-
cmd: 'connack',
|
|
125
|
-
returnCode: 5,
|
|
126
|
-
length: 2,
|
|
127
|
-
qos: 0,
|
|
128
|
-
retain: false,
|
|
129
|
-
dup: false,
|
|
130
|
-
topic: null,
|
|
131
|
-
payload: null,
|
|
132
|
-
sessionPresent: false
|
|
133
|
-
}, 'unsuccessful connack, unauthorized')
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
eos(s.outStream, function () {
|
|
137
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
s.inStream.write({
|
|
141
|
-
cmd: 'connect',
|
|
142
|
-
protocolId: 'MQTT',
|
|
143
|
-
protocolVersion: 4,
|
|
144
|
-
clean: true,
|
|
145
|
-
clientId: 'my-client',
|
|
146
|
-
username: 'my username',
|
|
147
|
-
password: 'my pass',
|
|
148
|
-
keepalive: 0
|
|
149
|
-
})
|
|
105
|
+
test('authenticate errors', async (t) => {
|
|
106
|
+
t.plan(8)
|
|
107
|
+
const error = new Error('Auth error')
|
|
108
|
+
error.returnCode = 1
|
|
109
|
+
await testAuthenticationError(t, error, 5)
|
|
150
110
|
})
|
|
151
111
|
|
|
152
|
-
test('authentication error when return code 1 (unacceptable protocol version) is passed',
|
|
153
|
-
t.plan(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
t
|
|
157
|
-
|
|
158
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
159
|
-
t.type(client, Client, 'client is there')
|
|
160
|
-
t.equal(username, 'my username', 'username is there')
|
|
161
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
162
|
-
const error = new Error('Auth error')
|
|
163
|
-
error.returnCode = 1
|
|
164
|
-
cb(error, null)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
s.broker.on('clientError', function (client, err) {
|
|
168
|
-
t.equal(err.message, 'Auth error')
|
|
169
|
-
t.equal(err.errorCode, 5)
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
s.broker.on('clientReady', function (client) {
|
|
173
|
-
t.fail('client should not ready')
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
s.outStream.on('data', function (packet) {
|
|
177
|
-
t.same(packet, {
|
|
178
|
-
cmd: 'connack',
|
|
179
|
-
returnCode: 5,
|
|
180
|
-
length: 2,
|
|
181
|
-
qos: 0,
|
|
182
|
-
retain: false,
|
|
183
|
-
dup: false,
|
|
184
|
-
topic: null,
|
|
185
|
-
payload: null,
|
|
186
|
-
sessionPresent: false
|
|
187
|
-
}, 'unsuccessful connack, unauthorized')
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
eos(s.outStream, function () {
|
|
191
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
s.inStream.write({
|
|
195
|
-
cmd: 'connect',
|
|
196
|
-
protocolId: 'MQTT',
|
|
197
|
-
protocolVersion: 4,
|
|
198
|
-
clean: true,
|
|
199
|
-
clientId: 'my-client',
|
|
200
|
-
username: 'my username',
|
|
201
|
-
password: 'my pass',
|
|
202
|
-
keepalive: 0
|
|
203
|
-
})
|
|
112
|
+
test('authentication error when return code 1 (unacceptable protocol version) is passed', async (t) => {
|
|
113
|
+
t.plan(8)
|
|
114
|
+
const error = new Error('Auth error')
|
|
115
|
+
error.returnCode = 1
|
|
116
|
+
await testAuthenticationError(t, error, 5)
|
|
204
117
|
})
|
|
205
118
|
|
|
206
|
-
test('authentication error when return code 2 (identifier rejected) is passed',
|
|
207
|
-
t.plan(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
t
|
|
211
|
-
|
|
212
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
213
|
-
t.type(client, Client, 'client is there')
|
|
214
|
-
t.equal(username, 'my username', 'username is there')
|
|
215
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
216
|
-
const error = new Error('Auth error')
|
|
217
|
-
error.returnCode = 2
|
|
218
|
-
cb(error, null)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
s.broker.on('clientError', function (client, err) {
|
|
222
|
-
t.equal(err.message, 'Auth error')
|
|
223
|
-
t.equal(err.errorCode, 2)
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
s.broker.on('clientReady', function (client) {
|
|
227
|
-
t.fail('client should not ready')
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
s.outStream.on('data', function (packet) {
|
|
231
|
-
t.same(packet, {
|
|
232
|
-
cmd: 'connack',
|
|
233
|
-
returnCode: 2,
|
|
234
|
-
length: 2,
|
|
235
|
-
qos: 0,
|
|
236
|
-
retain: false,
|
|
237
|
-
dup: false,
|
|
238
|
-
topic: null,
|
|
239
|
-
payload: null,
|
|
240
|
-
sessionPresent: false
|
|
241
|
-
}, 'unsuccessful connack, identifier rejected')
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
eos(s.outStream, function () {
|
|
245
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
s.inStream.write({
|
|
249
|
-
cmd: 'connect',
|
|
250
|
-
protocolId: 'MQTT',
|
|
251
|
-
protocolVersion: 4,
|
|
252
|
-
clean: true,
|
|
253
|
-
clientId: 'my-client',
|
|
254
|
-
username: 'my username',
|
|
255
|
-
password: 'my pass',
|
|
256
|
-
keepalive: 0
|
|
257
|
-
})
|
|
119
|
+
test('authentication error when return code 2 (identifier rejected) is passed', async (t) => {
|
|
120
|
+
t.plan(8)
|
|
121
|
+
const error = new Error('Auth error')
|
|
122
|
+
error.returnCode = 2
|
|
123
|
+
await testAuthenticationError(t, error, 2)
|
|
258
124
|
})
|
|
259
125
|
|
|
260
|
-
test('authentication error when return code 3 (Server unavailable) is passed',
|
|
261
|
-
t.plan(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
t
|
|
265
|
-
|
|
266
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
267
|
-
t.type(client, Client, 'client is there')
|
|
268
|
-
t.equal(username, 'my username', 'username is there')
|
|
269
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
270
|
-
const error = new Error('Auth error')
|
|
271
|
-
error.returnCode = 3
|
|
272
|
-
cb(error, null)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
s.broker.on('clientError', function (client, err) {
|
|
276
|
-
t.equal(err.message, 'Auth error')
|
|
277
|
-
t.equal(err.errorCode, 3)
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
s.broker.on('clientReady', function (client) {
|
|
281
|
-
t.fail('client should not ready')
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
s.outStream.on('data', function (packet) {
|
|
285
|
-
t.same(packet, {
|
|
286
|
-
cmd: 'connack',
|
|
287
|
-
returnCode: 3,
|
|
288
|
-
length: 2,
|
|
289
|
-
qos: 0,
|
|
290
|
-
retain: false,
|
|
291
|
-
dup: false,
|
|
292
|
-
topic: null,
|
|
293
|
-
payload: null,
|
|
294
|
-
sessionPresent: false
|
|
295
|
-
}, 'unsuccessful connack, Server unavailable')
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
eos(s.outStream, function () {
|
|
299
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
s.inStream.write({
|
|
303
|
-
cmd: 'connect',
|
|
304
|
-
protocolId: 'MQTT',
|
|
305
|
-
protocolVersion: 4,
|
|
306
|
-
clean: true,
|
|
307
|
-
clientId: 'my-client',
|
|
308
|
-
username: 'my username',
|
|
309
|
-
password: 'my pass',
|
|
310
|
-
keepalive: 0
|
|
311
|
-
})
|
|
126
|
+
test('authentication error when return code 3 (Server unavailable) is passed', async (t) => {
|
|
127
|
+
t.plan(8)
|
|
128
|
+
const error = new Error('Auth error')
|
|
129
|
+
error.returnCode = 3
|
|
130
|
+
await testAuthenticationError(t, error, 3)
|
|
312
131
|
})
|
|
313
132
|
|
|
314
|
-
test('authentication error when return code 4 (bad user or password) is passed',
|
|
315
|
-
t.plan(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
t
|
|
319
|
-
|
|
320
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
321
|
-
t.type(client, Client, 'client is there')
|
|
322
|
-
t.equal(username, 'my username', 'username is there')
|
|
323
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
324
|
-
const error = new Error('Auth error')
|
|
325
|
-
error.returnCode = 4
|
|
326
|
-
cb(error, null)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
s.broker.on('clientError', function (client, err) {
|
|
330
|
-
t.equal(err.message, 'Auth error')
|
|
331
|
-
t.equal(err.errorCode, 4)
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
s.broker.on('clientReady', function (client) {
|
|
335
|
-
t.fail('client should not ready')
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
s.outStream.on('data', function (packet) {
|
|
339
|
-
t.same(packet, {
|
|
340
|
-
cmd: 'connack',
|
|
341
|
-
returnCode: 4,
|
|
342
|
-
length: 2,
|
|
343
|
-
qos: 0,
|
|
344
|
-
retain: false,
|
|
345
|
-
dup: false,
|
|
346
|
-
topic: null,
|
|
347
|
-
payload: null,
|
|
348
|
-
sessionPresent: false
|
|
349
|
-
}, 'unsuccessful connack, bad username or password')
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
eos(s.outStream, function () {
|
|
353
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
s.inStream.write({
|
|
357
|
-
cmd: 'connect',
|
|
358
|
-
protocolId: 'MQTT',
|
|
359
|
-
protocolVersion: 4,
|
|
360
|
-
clean: true,
|
|
361
|
-
clientId: 'my-client',
|
|
362
|
-
username: 'my username',
|
|
363
|
-
password: 'my pass',
|
|
364
|
-
keepalive: 0
|
|
365
|
-
})
|
|
133
|
+
test('authentication error when return code 4 (bad user or password) is passed', async (t) => {
|
|
134
|
+
t.plan(8)
|
|
135
|
+
const error = new Error('Auth error')
|
|
136
|
+
error.returnCode = 4
|
|
137
|
+
await testAuthenticationError(t, error, 4)
|
|
366
138
|
})
|
|
367
139
|
|
|
368
|
-
test('authentication error when non numeric return code is passed',
|
|
369
|
-
t.plan(
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
t
|
|
373
|
-
|
|
374
|
-
s.broker.authenticate = function (client, username, password, cb) {
|
|
375
|
-
t.type(client, Client, 'client is there')
|
|
376
|
-
t.equal(username, 'my username', 'username is there')
|
|
377
|
-
t.same(password, Buffer.from('my pass'), 'password is there')
|
|
378
|
-
const error = new Error('Non numeric error codes')
|
|
379
|
-
error.returnCode = 'return Code'
|
|
380
|
-
cb(error, null)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
s.broker.on('clientError', function (client, err) {
|
|
384
|
-
t.equal(err.message, 'Non numeric error codes')
|
|
385
|
-
t.equal(err.errorCode, 5)
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
s.broker.on('clientReady', function (client) {
|
|
389
|
-
t.fail('client should not ready')
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
s.outStream.on('data', function (packet) {
|
|
393
|
-
t.same(packet, {
|
|
394
|
-
cmd: 'connack',
|
|
395
|
-
returnCode: 5,
|
|
396
|
-
length: 2,
|
|
397
|
-
qos: 0,
|
|
398
|
-
retain: false,
|
|
399
|
-
dup: false,
|
|
400
|
-
topic: null,
|
|
401
|
-
payload: null,
|
|
402
|
-
sessionPresent: false
|
|
403
|
-
}, 'unsuccessful connack, unauthorized')
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
eos(s.outStream, function () {
|
|
407
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
s.inStream.write({
|
|
411
|
-
cmd: 'connect',
|
|
412
|
-
protocolId: 'MQTT',
|
|
413
|
-
protocolVersion: 4,
|
|
414
|
-
clean: true,
|
|
415
|
-
clientId: 'my-client',
|
|
416
|
-
username: 'my username',
|
|
417
|
-
password: 'my pass',
|
|
418
|
-
keepalive: 0
|
|
419
|
-
})
|
|
140
|
+
test('authentication error when non numeric return code is passed', async (t) => {
|
|
141
|
+
t.plan(8)
|
|
142
|
+
const error = new Error('Auth error')
|
|
143
|
+
error.returnCode = 'return Code'
|
|
144
|
+
await testAuthenticationError(t, error, 5)
|
|
420
145
|
})
|
|
421
146
|
|
|
422
|
-
test('authorize publish',
|
|
147
|
+
test('authorize publish', async (t) => {
|
|
423
148
|
t.plan(4)
|
|
424
|
-
|
|
425
|
-
const s = connect(setup(), { clientId: 'my-client-xyz' })
|
|
426
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
427
|
-
|
|
428
149
|
const expected = {
|
|
429
150
|
cmd: 'publish',
|
|
430
151
|
topic: 'hello',
|
|
@@ -435,47 +156,58 @@ test('authorize publish', function (t) {
|
|
|
435
156
|
dup: false
|
|
436
157
|
}
|
|
437
158
|
|
|
438
|
-
s
|
|
439
|
-
|
|
440
|
-
|
|
159
|
+
const s = await createAndConnect(t)
|
|
160
|
+
|
|
161
|
+
s.broker.authorizePublish = (client, packet, cb) => {
|
|
162
|
+
t.assert.ok(client, 'client exists')
|
|
163
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
441
164
|
cb()
|
|
442
165
|
}
|
|
443
166
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
167
|
+
const packet = await new Promise((resolve) => {
|
|
168
|
+
s.broker.mq.on('hello', (packet, cb) => {
|
|
169
|
+
resolve(packet)
|
|
170
|
+
cb()
|
|
171
|
+
})
|
|
172
|
+
s.inStream.write({
|
|
173
|
+
cmd: 'publish',
|
|
174
|
+
topic: 'hello',
|
|
175
|
+
payload: 'world'
|
|
176
|
+
})
|
|
452
177
|
})
|
|
453
|
-
|
|
454
178
|
s.inStream.write({
|
|
455
179
|
cmd: 'publish',
|
|
456
180
|
topic: 'hello',
|
|
457
181
|
payload: 'world'
|
|
458
182
|
})
|
|
183
|
+
|
|
184
|
+
t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
|
|
185
|
+
expected.brokerId = s.broker.id
|
|
186
|
+
expected.brokerCounter = s.broker.counter
|
|
187
|
+
expected.clientId = 'my-client'
|
|
188
|
+
delete expected.length
|
|
189
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
|
|
459
190
|
})
|
|
460
191
|
|
|
461
|
-
test('authorize waits for authenticate',
|
|
192
|
+
test('authorize waits for authenticate', async (t) => {
|
|
462
193
|
t.plan(6)
|
|
463
194
|
|
|
464
|
-
const
|
|
465
|
-
t.
|
|
195
|
+
const broker = await Aedes.createBroker()
|
|
196
|
+
t.after(() => broker.close())
|
|
197
|
+
const s = setup(broker)
|
|
466
198
|
|
|
467
|
-
|
|
468
|
-
t.
|
|
469
|
-
process.nextTick(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
})
|
|
199
|
+
broker.authenticate = (client, username, password, cb) => {
|
|
200
|
+
t.assert.equal(client instanceof Client, true, 'client is there')
|
|
201
|
+
// process.nextTick(() => {
|
|
202
|
+
t.assert.equal(username, 'my username', 'username is there')
|
|
203
|
+
t.assert.equal(password.toString(), 'my pass', 'password is there')
|
|
204
|
+
client.authenticated = true
|
|
205
|
+
cb(null, true)
|
|
206
|
+
// })
|
|
475
207
|
}
|
|
476
208
|
|
|
477
|
-
|
|
478
|
-
t.
|
|
209
|
+
broker.authorizePublish = (client, _packet, cb) => {
|
|
210
|
+
t.assert.equal(client.authenticated, true, 'client authenticated')
|
|
479
211
|
cb()
|
|
480
212
|
}
|
|
481
213
|
|
|
@@ -490,46 +222,39 @@ test('authorize waits for authenticate', function (t) {
|
|
|
490
222
|
clientId: 'my-client'
|
|
491
223
|
}
|
|
492
224
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
225
|
+
await new Promise((resolve) => {
|
|
226
|
+
s.broker.mq.on('hello', (packet, cb) => {
|
|
227
|
+
t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
|
|
228
|
+
expected.brokerId = s.broker.id
|
|
229
|
+
expected.brokerCounter = s.broker.counter
|
|
230
|
+
delete expected.length
|
|
231
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
|
|
232
|
+
cb()
|
|
233
|
+
resolve()
|
|
234
|
+
})
|
|
501
235
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
236
|
+
s.inStream.write({
|
|
237
|
+
cmd: 'connect',
|
|
238
|
+
protocolId: 'MQTT',
|
|
239
|
+
protocolVersion: 4,
|
|
240
|
+
clean: true,
|
|
241
|
+
clientId: 'my-client',
|
|
242
|
+
username: 'my username',
|
|
243
|
+
password: 'my pass',
|
|
244
|
+
keepalive: 0
|
|
245
|
+
})
|
|
512
246
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
247
|
+
s.inStream.write({
|
|
248
|
+
cmd: 'publish',
|
|
249
|
+
topic: 'hello',
|
|
250
|
+
payload: 'world'
|
|
251
|
+
})
|
|
517
252
|
})
|
|
518
253
|
})
|
|
519
254
|
|
|
520
|
-
test('authorize publish from configOptions',
|
|
255
|
+
test('authorize publish from configOptions', async (t) => {
|
|
521
256
|
t.plan(4)
|
|
522
257
|
|
|
523
|
-
const s = connect(setup(aedes({
|
|
524
|
-
clientId: 'my-client-xyz-3',
|
|
525
|
-
authorizePublish: function (client, packet, cb) {
|
|
526
|
-
t.ok(client, 'client exists')
|
|
527
|
-
t.same(packet, expected, 'packet matches')
|
|
528
|
-
cb()
|
|
529
|
-
}
|
|
530
|
-
})), { clientId: 'my-client-xyz-3' })
|
|
531
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
532
|
-
|
|
533
258
|
const expected = {
|
|
534
259
|
cmd: 'publish',
|
|
535
260
|
topic: 'hello',
|
|
@@ -540,29 +265,38 @@ test('authorize publish from configOptions', function (t) {
|
|
|
540
265
|
dup: false
|
|
541
266
|
}
|
|
542
267
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
t.same(packet, expected, 'packet matches')
|
|
550
|
-
cb()
|
|
268
|
+
const broker = await Aedes.createBroker({
|
|
269
|
+
authorizePublish: (client, packet, cb) => {
|
|
270
|
+
t.assert.ok(client, 'client exists')
|
|
271
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
272
|
+
cb()
|
|
273
|
+
}
|
|
551
274
|
})
|
|
552
|
-
|
|
553
|
-
s
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
275
|
+
t.after(() => broker.close())
|
|
276
|
+
const s = setup(broker)
|
|
277
|
+
await connect(s)
|
|
278
|
+
|
|
279
|
+
await new Promise((resolve) => {
|
|
280
|
+
broker.mq.on('hello', (packet, cb) => {
|
|
281
|
+
t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
|
|
282
|
+
expected.brokerId = s.broker.id
|
|
283
|
+
expected.brokerCounter = s.broker.counter
|
|
284
|
+
delete expected.length
|
|
285
|
+
delete packet.clientId
|
|
286
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches again')
|
|
287
|
+
cb()
|
|
288
|
+
resolve()
|
|
289
|
+
})
|
|
290
|
+
s.inStream.write({
|
|
291
|
+
cmd: 'publish',
|
|
292
|
+
topic: 'hello',
|
|
293
|
+
payload: 'world'
|
|
294
|
+
})
|
|
557
295
|
})
|
|
558
296
|
})
|
|
559
297
|
|
|
560
|
-
test('do not authorize publish',
|
|
298
|
+
test('do not authorize publish', async (t) => {
|
|
561
299
|
t.plan(3)
|
|
562
|
-
|
|
563
|
-
const s = connect(setup())
|
|
564
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
565
|
-
|
|
566
300
|
const expected = {
|
|
567
301
|
cmd: 'publish',
|
|
568
302
|
topic: 'hello',
|
|
@@ -573,28 +307,25 @@ test('do not authorize publish', function (t) {
|
|
|
573
307
|
dup: false
|
|
574
308
|
}
|
|
575
309
|
|
|
576
|
-
s
|
|
577
|
-
|
|
578
|
-
|
|
310
|
+
const s = await createAndConnect(t)
|
|
311
|
+
|
|
312
|
+
s.broker.authorizePublish = (client, packet, cb) => {
|
|
313
|
+
t.assert.ok(client, 'client exists')
|
|
314
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
579
315
|
cb(new Error('auth negated'))
|
|
580
316
|
}
|
|
581
317
|
|
|
582
|
-
eos(s.conn, function () {
|
|
583
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
584
|
-
})
|
|
585
|
-
|
|
586
318
|
s.inStream.write({
|
|
587
319
|
cmd: 'publish',
|
|
588
320
|
topic: 'hello',
|
|
589
321
|
payload: 'world'
|
|
590
322
|
})
|
|
323
|
+
await once(s.broker, 'clientError')
|
|
324
|
+
t.assert.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
591
325
|
})
|
|
592
326
|
|
|
593
|
-
test('modify qos out of range in authorize publish ',
|
|
594
|
-
t.plan(
|
|
595
|
-
|
|
596
|
-
const s = connect(setup(), { clientId: 'my-client-xyz-4' })
|
|
597
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
327
|
+
test('modify qos out of range in authorize publish ', async (t) => {
|
|
328
|
+
t.plan(3)
|
|
598
329
|
|
|
599
330
|
const expected = {
|
|
600
331
|
cmd: 'publish',
|
|
@@ -607,105 +338,106 @@ test('modify qos out of range in authorize publish ', function (t) {
|
|
|
607
338
|
clientId: 'my-client-xyz-4'
|
|
608
339
|
}
|
|
609
340
|
|
|
610
|
-
s
|
|
341
|
+
const s = await createAndConnect(t, { connect: { clientId: 'my-client-xyz-4' } })
|
|
342
|
+
|
|
343
|
+
s.broker.authorizePublish = (client, packet, cb) => {
|
|
611
344
|
if (packet.topic === 'hello') { packet.qos = 10 }
|
|
612
345
|
cb()
|
|
613
346
|
}
|
|
614
347
|
|
|
615
|
-
s.
|
|
616
|
-
t.fail('should
|
|
617
|
-
})
|
|
618
|
-
s.broker.mq.on('hello', function (packet, cb) {
|
|
619
|
-
t.fail('should not publish')
|
|
620
|
-
})
|
|
621
|
-
s.broker.mq.on('foo', function (packet, cb) {
|
|
622
|
-
t.notOk(Object.prototype.hasOwnProperty.call(packet, 'messageId'), 'should not contain messageId in QoS 0')
|
|
623
|
-
expected.brokerId = s.broker.id
|
|
624
|
-
expected.brokerCounter = s.broker.counter
|
|
625
|
-
delete expected.length
|
|
626
|
-
t.same(packet, expected, 'packet matches')
|
|
627
|
-
cb()
|
|
348
|
+
s.broker.mq.on('hello', (packet, cb) => {
|
|
349
|
+
t.assert.fail('should not publish')
|
|
628
350
|
})
|
|
629
351
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
352
|
+
await new Promise((resolve) => {
|
|
353
|
+
s.broker.mq.on('foo', (packet, cb) => {
|
|
354
|
+
t.assert.equal(Object.hasOwn(packet, 'messageId'), false, 'should not contain messageId in QoS 0')
|
|
355
|
+
expected.brokerId = s.broker.id
|
|
356
|
+
expected.brokerCounter = s.broker.counter
|
|
357
|
+
delete expected.length
|
|
358
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
359
|
+
resolve()
|
|
360
|
+
cb()
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
s.inStream.write({
|
|
364
|
+
cmd: 'publish',
|
|
365
|
+
topic: 'hello',
|
|
366
|
+
payload: 'world'
|
|
367
|
+
})
|
|
368
|
+
s.inStream.write({
|
|
369
|
+
cmd: 'publish',
|
|
370
|
+
topic: 'foo',
|
|
371
|
+
payload: 'bar'
|
|
372
|
+
})
|
|
639
373
|
})
|
|
374
|
+
const result = await nextPacketWithTimeOut(s, 1)
|
|
375
|
+
t.assert.equal(result, null, 'no packet')
|
|
640
376
|
})
|
|
641
377
|
|
|
642
|
-
test('authorize subscribe',
|
|
378
|
+
test('authorize subscribe', async (t) => {
|
|
643
379
|
t.plan(5)
|
|
644
380
|
|
|
645
|
-
const s =
|
|
646
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
381
|
+
const s = await createAndConnect(t)
|
|
647
382
|
|
|
648
|
-
s.broker.authorizeSubscribe =
|
|
649
|
-
t.ok(client, 'client exists')
|
|
650
|
-
t.
|
|
383
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
384
|
+
t.assert.ok(client, 'client exists')
|
|
385
|
+
t.assert.deepEqual(sub, {
|
|
651
386
|
topic: 'hello',
|
|
652
387
|
qos: 0
|
|
653
388
|
}, 'topic matches')
|
|
654
389
|
cb(null, sub)
|
|
655
390
|
}
|
|
656
391
|
|
|
657
|
-
subscribe(t, s, 'hello', 0)
|
|
392
|
+
await subscribe(t, s, 'hello', 0)
|
|
658
393
|
})
|
|
659
394
|
|
|
660
|
-
test('authorize subscribe multiple same topics with same qos',
|
|
395
|
+
test('authorize subscribe multiple same topics with same qos', async (t) => {
|
|
661
396
|
t.plan(4)
|
|
662
397
|
|
|
663
|
-
const s =
|
|
664
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
398
|
+
const s = await createAndConnect(t)
|
|
665
399
|
|
|
666
|
-
s.broker.authorizeSubscribe =
|
|
667
|
-
t.
|
|
400
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
401
|
+
t.assert.deepEqual(sub, {
|
|
668
402
|
topic: 'hello',
|
|
669
403
|
qos: 0
|
|
670
404
|
}, 'topic matches')
|
|
671
405
|
cb(null, sub)
|
|
672
406
|
}
|
|
673
407
|
|
|
674
|
-
subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 0 }], [0])
|
|
408
|
+
await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 0 }], [0])
|
|
675
409
|
})
|
|
676
410
|
|
|
677
|
-
test('authorize subscribe multiple same topics with different qos',
|
|
411
|
+
test('authorize subscribe multiple same topics with different qos', async (t) => {
|
|
678
412
|
t.plan(4)
|
|
679
413
|
|
|
680
|
-
const s =
|
|
681
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
414
|
+
const s = await createAndConnect(t)
|
|
682
415
|
|
|
683
|
-
s.broker.authorizeSubscribe =
|
|
684
|
-
t.
|
|
416
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
417
|
+
t.assert.deepEqual(sub, {
|
|
685
418
|
topic: 'hello',
|
|
686
419
|
qos: 1
|
|
687
420
|
}, 'topic matches')
|
|
688
421
|
cb(null, sub)
|
|
689
422
|
}
|
|
690
423
|
|
|
691
|
-
subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 1 }], [1])
|
|
424
|
+
await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'hello', qos: 1 }], [1])
|
|
692
425
|
})
|
|
693
426
|
|
|
694
|
-
test('authorize subscribe multiple different topics',
|
|
427
|
+
test('authorize subscribe multiple different topics', async (t) => {
|
|
695
428
|
t.plan(7)
|
|
696
429
|
|
|
697
|
-
const s =
|
|
698
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
430
|
+
const s = await createAndConnect(t)
|
|
699
431
|
|
|
700
|
-
s.broker.authorizeSubscribe =
|
|
701
|
-
t.ok(client, 'client exists')
|
|
432
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
433
|
+
t.assert.ok(client, 'client exists')
|
|
702
434
|
if (sub.topic === 'hello') {
|
|
703
|
-
t.
|
|
435
|
+
t.assert.deepEqual(sub, {
|
|
704
436
|
topic: 'hello',
|
|
705
437
|
qos: 0
|
|
706
438
|
}, 'topic matches')
|
|
707
439
|
} else if (sub.topic === 'foo') {
|
|
708
|
-
t.
|
|
440
|
+
t.assert.deepEqual(sub, {
|
|
709
441
|
topic: 'foo',
|
|
710
442
|
qos: 0
|
|
711
443
|
}, 'topic matches')
|
|
@@ -713,66 +445,51 @@ test('authorize subscribe multiple different topics', function (t) {
|
|
|
713
445
|
cb(null, sub)
|
|
714
446
|
}
|
|
715
447
|
|
|
716
|
-
subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'foo', qos: 0 }], [0, 0])
|
|
448
|
+
await subscribeMultiple(t, s, [{ topic: 'hello', qos: 0 }, { topic: 'foo', qos: 0 }], [0, 0])
|
|
717
449
|
})
|
|
718
450
|
|
|
719
|
-
test('authorize subscribe from config options',
|
|
451
|
+
test('authorize subscribe from config options', async (t) => {
|
|
720
452
|
t.plan(5)
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
t.
|
|
725
|
-
t.same(sub, {
|
|
453
|
+
const broker = await Aedes.createBroker({
|
|
454
|
+
authorizeSubscribe: (client, sub, cb) => {
|
|
455
|
+
t.assert.ok(client, 'client exists')
|
|
456
|
+
t.assert.deepEqual(sub, {
|
|
726
457
|
topic: 'hello',
|
|
727
458
|
qos: 0
|
|
728
459
|
}, 'topic matches')
|
|
729
460
|
cb(null, sub)
|
|
730
461
|
}
|
|
731
|
-
})
|
|
732
|
-
t.
|
|
733
|
-
|
|
734
|
-
|
|
462
|
+
})
|
|
463
|
+
t.after(() => broker.close())
|
|
464
|
+
const s = setup(broker)
|
|
465
|
+
await connect(s)
|
|
466
|
+
await subscribe(t, s, 'hello', 0)
|
|
735
467
|
})
|
|
736
468
|
|
|
737
|
-
test('negate subscription',
|
|
469
|
+
test('negate subscription', async (t) => {
|
|
738
470
|
t.plan(5)
|
|
739
471
|
|
|
740
|
-
const s =
|
|
741
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
472
|
+
const s = await createAndConnect(t)
|
|
742
473
|
|
|
743
|
-
s.broker.authorizeSubscribe =
|
|
744
|
-
t.ok(client, 'client exists')
|
|
745
|
-
t.
|
|
474
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
475
|
+
t.assert.ok(client, 'client exists')
|
|
476
|
+
t.assert.deepEqual(sub, {
|
|
746
477
|
topic: 'hello',
|
|
747
478
|
qos: 0
|
|
748
479
|
}, 'topic matches')
|
|
749
480
|
cb(null, null)
|
|
750
481
|
}
|
|
751
482
|
|
|
752
|
-
s
|
|
753
|
-
cmd: 'subscribe',
|
|
754
|
-
messageId: 24,
|
|
755
|
-
subscriptions: [{
|
|
756
|
-
topic: 'hello',
|
|
757
|
-
qos: 0
|
|
758
|
-
}]
|
|
759
|
-
})
|
|
760
|
-
|
|
761
|
-
s.outStream.once('data', function (packet) {
|
|
762
|
-
t.equal(packet.cmd, 'suback')
|
|
763
|
-
t.same(packet.granted, [128])
|
|
764
|
-
t.equal(packet.messageId, 24)
|
|
765
|
-
})
|
|
483
|
+
await subscribe(t, s, 'hello', 128)
|
|
766
484
|
})
|
|
767
485
|
|
|
768
|
-
test('negate multiple subscriptions',
|
|
486
|
+
test('negate multiple subscriptions', async (t) => {
|
|
769
487
|
t.plan(6)
|
|
770
488
|
|
|
771
|
-
const s =
|
|
772
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
489
|
+
const s = await createAndConnect(t)
|
|
773
490
|
|
|
774
|
-
s.broker.authorizeSubscribe =
|
|
775
|
-
t.ok(client, 'client exists')
|
|
491
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
492
|
+
t.assert.ok(client, 'client exists')
|
|
776
493
|
cb(null, null)
|
|
777
494
|
}
|
|
778
495
|
|
|
@@ -784,8 +501,8 @@ test('negate multiple subscriptions', function (t) {
|
|
|
784
501
|
qos: 128
|
|
785
502
|
}]
|
|
786
503
|
|
|
787
|
-
s.broker.once('subscribe',
|
|
788
|
-
t.
|
|
504
|
+
s.broker.once('subscribe', (subs, client) => {
|
|
505
|
+
t.assert.deepEqual(subs, expectedSubs)
|
|
789
506
|
})
|
|
790
507
|
|
|
791
508
|
s.inStream.write({
|
|
@@ -800,14 +517,13 @@ test('negate multiple subscriptions', function (t) {
|
|
|
800
517
|
}]
|
|
801
518
|
})
|
|
802
519
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
})
|
|
520
|
+
const packet = await nextPacket(s)
|
|
521
|
+
t.assert.equal(packet.cmd, 'suback')
|
|
522
|
+
t.assert.deepEqual(packet.granted, [128, 128])
|
|
523
|
+
t.assert.equal(packet.messageId, 24)
|
|
808
524
|
})
|
|
809
525
|
|
|
810
|
-
test('negate subscription with correct persistence',
|
|
526
|
+
test('negate subscription with correct persistence', async (t) => {
|
|
811
527
|
t.plan(6)
|
|
812
528
|
|
|
813
529
|
// rh, rap, nl are undefined because mqtt.parser is set to MQTT 3.1.1 and will thus erase these props from s.inStream.write
|
|
@@ -825,27 +541,16 @@ test('negate subscription with correct persistence', function (t) {
|
|
|
825
541
|
nl: undefined
|
|
826
542
|
}]
|
|
827
543
|
|
|
828
|
-
const
|
|
829
|
-
t.teardown(broker.close.bind(broker))
|
|
544
|
+
const s = await createAndConnect(t, { connect: { clean: false, clientId: 'abcde' } })
|
|
830
545
|
|
|
831
|
-
broker.authorizeSubscribe =
|
|
832
|
-
t.ok(client, 'client exists')
|
|
546
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
547
|
+
t.assert.ok(client, 'client exists')
|
|
833
548
|
if (sub.topic === 'hello') {
|
|
834
549
|
sub = null
|
|
835
550
|
}
|
|
836
551
|
cb(null, sub)
|
|
837
552
|
}
|
|
838
553
|
|
|
839
|
-
const s = connect(setup(broker), { clean: false, clientId: 'abcde' })
|
|
840
|
-
s.outStream.once('data', function (packet) {
|
|
841
|
-
t.equal(packet.cmd, 'suback')
|
|
842
|
-
t.same(packet.granted, [128, 0])
|
|
843
|
-
broker.persistence.subscriptionsByClient(broker.clients.abcde, function (_, subs, client) {
|
|
844
|
-
t.same(subs, expected)
|
|
845
|
-
})
|
|
846
|
-
t.equal(packet.messageId, 24)
|
|
847
|
-
})
|
|
848
|
-
|
|
849
554
|
s.inStream.write({
|
|
850
555
|
cmd: 'subscribe',
|
|
851
556
|
messageId: 24,
|
|
@@ -863,27 +568,31 @@ test('negate subscription with correct persistence', function (t) {
|
|
|
863
568
|
nl: false
|
|
864
569
|
}]
|
|
865
570
|
})
|
|
571
|
+
|
|
572
|
+
const packet = await nextPacket(s)
|
|
573
|
+
t.assert.equal(packet.cmd, 'suback')
|
|
574
|
+
t.assert.deepEqual(packet.granted, [128, 0])
|
|
575
|
+
const subs = await s.broker.persistence.subscriptionsByClient(s.broker.clients.abcde)
|
|
576
|
+
t.assert.deepEqual(subs, expected)
|
|
577
|
+
t.assert.equal(packet.messageId, 24)
|
|
866
578
|
})
|
|
867
579
|
|
|
868
|
-
test('negate multiple subscriptions random times',
|
|
580
|
+
test('negate multiple subscriptions random times', async (t) => {
|
|
869
581
|
t.plan(5)
|
|
870
582
|
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
t.
|
|
874
|
-
clock.reset()
|
|
875
|
-
s.broker.close()
|
|
876
|
-
})
|
|
583
|
+
const s = await createAndConnect(t)
|
|
584
|
+
// mock timers automatically disables at end of test
|
|
585
|
+
t.mock.timers.enable({ apis: ['setTimeout'] })
|
|
877
586
|
|
|
878
|
-
s.broker.authorizeSubscribe =
|
|
879
|
-
t.ok(client, 'client exists')
|
|
587
|
+
s.broker.authorizeSubscribe = (client, sub, cb) => {
|
|
588
|
+
t.assert.ok(client, 'client exists')
|
|
880
589
|
if (sub.topic === 'hello') {
|
|
881
|
-
|
|
590
|
+
setTimeout(() => {
|
|
882
591
|
cb(null, sub)
|
|
883
592
|
}, 100)
|
|
884
593
|
} else {
|
|
885
594
|
cb(null, null)
|
|
886
|
-
|
|
595
|
+
t.mock.timers.tick(100)
|
|
887
596
|
}
|
|
888
597
|
}
|
|
889
598
|
|
|
@@ -899,91 +608,48 @@ test('negate multiple subscriptions random times', function (t) {
|
|
|
899
608
|
}]
|
|
900
609
|
})
|
|
901
610
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
})
|
|
611
|
+
const packet = await nextPacket(s)
|
|
612
|
+
t.assert.equal(packet.cmd, 'suback')
|
|
613
|
+
t.assert.deepEqual(packet.granted, [0, 128])
|
|
614
|
+
t.assert.equal(packet.messageId, 24)
|
|
907
615
|
})
|
|
908
616
|
|
|
909
|
-
test('failed authentication does not disconnect other client with same clientId',
|
|
910
|
-
t.plan(
|
|
911
|
-
|
|
912
|
-
const broker = aedes()
|
|
913
|
-
t.teardown(broker.close.bind(broker))
|
|
617
|
+
test('failed authentication does not disconnect other client with same clientId', async (t) => {
|
|
618
|
+
t.plan(4)
|
|
914
619
|
|
|
620
|
+
const broker = await Aedes.createBroker()
|
|
621
|
+
t.after(() => broker.close())
|
|
915
622
|
const s = setup(broker)
|
|
916
623
|
const s0 = setup(broker)
|
|
917
624
|
|
|
918
|
-
broker.authenticate =
|
|
625
|
+
broker.authenticate = (client, username, password, cb) => {
|
|
919
626
|
cb(null, password.toString() === 'right')
|
|
920
627
|
}
|
|
921
628
|
|
|
922
|
-
s0
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
retain: false,
|
|
940
|
-
dup: false,
|
|
941
|
-
topic: null,
|
|
942
|
-
payload: null,
|
|
943
|
-
sessionPresent: false
|
|
944
|
-
}, 'successful connack')
|
|
945
|
-
|
|
946
|
-
s.inStream.write({
|
|
947
|
-
cmd: 'connect',
|
|
948
|
-
protocolId: 'MQTT',
|
|
949
|
-
protocolVersion: 4,
|
|
950
|
-
clean: true,
|
|
951
|
-
clientId: 'my-client',
|
|
952
|
-
username: 'my username',
|
|
953
|
-
password: 'wrong',
|
|
954
|
-
keepalive: 0
|
|
955
|
-
})
|
|
956
|
-
})
|
|
957
|
-
|
|
958
|
-
const removeEos = eos(s0.outStream, function () {
|
|
959
|
-
t.fail('ended before time')
|
|
960
|
-
})
|
|
961
|
-
|
|
962
|
-
s.outStream.on('data', function (packet) {
|
|
963
|
-
t.same(packet, {
|
|
964
|
-
cmd: 'connack',
|
|
965
|
-
returnCode: 5,
|
|
966
|
-
length: 2,
|
|
967
|
-
qos: 0,
|
|
968
|
-
retain: false,
|
|
969
|
-
dup: false,
|
|
970
|
-
topic: null,
|
|
971
|
-
payload: null,
|
|
972
|
-
sessionPresent: false
|
|
973
|
-
}, 'unsuccessful connack')
|
|
974
|
-
})
|
|
975
|
-
|
|
976
|
-
eos(s.outStream, function () {
|
|
977
|
-
t.pass('ended')
|
|
978
|
-
removeEos()
|
|
979
|
-
})
|
|
629
|
+
await connect(s0, { connect: { password: 'right' } })
|
|
630
|
+
const packet = await connect(s, { connect: { password: 'wrong' }, verifyReturnedOk: false })
|
|
631
|
+
t.assert.deepEqual(packet, {
|
|
632
|
+
cmd: 'connack',
|
|
633
|
+
returnCode: 5,
|
|
634
|
+
length: 2,
|
|
635
|
+
qos: 0,
|
|
636
|
+
retain: false,
|
|
637
|
+
dup: false,
|
|
638
|
+
topic: null,
|
|
639
|
+
payload: null,
|
|
640
|
+
sessionPresent: false
|
|
641
|
+
}, 'unsuccessful connack')
|
|
642
|
+
t.assert.equal(broker.connectedClients, 1, 'only one client connected')
|
|
643
|
+
await once(s.conn, 'close')
|
|
644
|
+
t.assert.equal(s0.conn.closed, false, 's0 is still connected')
|
|
645
|
+
t.assert.equal(s.conn.closed, true, 's has been disconnected')
|
|
980
646
|
})
|
|
981
647
|
|
|
982
|
-
test('unauthorized connection should not unregister the correct one with same clientId',
|
|
983
|
-
t.plan(
|
|
648
|
+
test('unauthorized connection should not unregister the correct one with same clientId', async (t) => {
|
|
649
|
+
t.plan(3)
|
|
984
650
|
|
|
985
|
-
const broker =
|
|
986
|
-
authenticate:
|
|
651
|
+
const broker = await Aedes.createBroker({
|
|
652
|
+
authenticate: (client, username, password, callback) => {
|
|
987
653
|
if (username === 'correct') {
|
|
988
654
|
callback(null, true)
|
|
989
655
|
} else {
|
|
@@ -993,83 +659,71 @@ test('unauthorized connection should not unregister the correct one with same cl
|
|
|
993
659
|
}
|
|
994
660
|
}
|
|
995
661
|
})
|
|
996
|
-
t.
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
t.equal(err.message, 'bad user name or password')
|
|
1000
|
-
t.equal(err.errorCode, 4)
|
|
1001
|
-
t.equal(broker.connectedClients, 1, 'my-client still connected')
|
|
1002
|
-
})
|
|
662
|
+
t.after(() => broker.close())
|
|
663
|
+
const s = setup(broker)
|
|
664
|
+
const s0 = setup(broker)
|
|
1003
665
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
clientId: 'my-client',
|
|
1011
|
-
username: 'unauthorized'
|
|
1012
|
-
}, function () {
|
|
1013
|
-
// other unauthorized connection with the same clientId should not unregister the correct one.
|
|
1014
|
-
t.fail('unauthorized should not connect')
|
|
666
|
+
const catchClientError = new Promise(resolve => {
|
|
667
|
+
broker.on('clientError', (client, err) => {
|
|
668
|
+
t.assert.equal(err.message, 'bad user name or password')
|
|
669
|
+
t.assert.equal(err.errorCode, 4)
|
|
670
|
+
t.assert.equal(broker.connectedClients, 1, 'my-client still connected')
|
|
671
|
+
resolve()
|
|
1015
672
|
})
|
|
1016
673
|
})
|
|
674
|
+
const serialConnect = async () => {
|
|
675
|
+
await connect(s0, { connect: { username: 'correct' } })
|
|
676
|
+
await connect(s, { connect: { username: 'unauthorized' }, expectedReturnCode: 4 })
|
|
677
|
+
}
|
|
678
|
+
await Promise.all([
|
|
679
|
+
catchClientError,
|
|
680
|
+
serialConnect()
|
|
681
|
+
])
|
|
1017
682
|
})
|
|
1018
683
|
|
|
1019
|
-
test('set authentication method in config options',
|
|
1020
|
-
t.plan(
|
|
684
|
+
test('set authentication method in config options', async (t) => {
|
|
685
|
+
t.plan(6)
|
|
1021
686
|
|
|
1022
|
-
const
|
|
1023
|
-
authenticate:
|
|
1024
|
-
t.
|
|
1025
|
-
t.equal(username, 'my username', 'username is there')
|
|
1026
|
-
t.
|
|
687
|
+
const broker = await Aedes.createBroker({
|
|
688
|
+
authenticate: (client, username, password, cb) => {
|
|
689
|
+
t.assert.equal(client instanceof Client, true, 'client is there')
|
|
690
|
+
t.assert.equal(username, 'my username', 'username is there')
|
|
691
|
+
t.assert.deepEqual(password, Buffer.from('my pass'), 'password is there')
|
|
1027
692
|
cb(null, false)
|
|
1028
693
|
}
|
|
1029
|
-
}))
|
|
1030
|
-
t.teardown(s.broker.close.bind(s.broker))
|
|
1031
|
-
|
|
1032
|
-
s.outStream.on('data', function (packet) {
|
|
1033
|
-
t.same(packet, {
|
|
1034
|
-
cmd: 'connack',
|
|
1035
|
-
returnCode: 5,
|
|
1036
|
-
length: 2,
|
|
1037
|
-
qos: 0,
|
|
1038
|
-
retain: false,
|
|
1039
|
-
dup: false,
|
|
1040
|
-
topic: null,
|
|
1041
|
-
payload: null,
|
|
1042
|
-
sessionPresent: false
|
|
1043
|
-
}, 'unsuccessful connack')
|
|
1044
|
-
})
|
|
1045
|
-
|
|
1046
|
-
eos(s.outStream, function () {
|
|
1047
|
-
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
1048
694
|
})
|
|
695
|
+
t.after(() => broker.close())
|
|
696
|
+
const s = setup(broker)
|
|
697
|
+
const packet = await connect(s, { verifyReturnedOk: false })
|
|
1049
698
|
|
|
1050
|
-
|
|
1051
|
-
cmd: '
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
699
|
+
t.assert.deepEqual(packet, {
|
|
700
|
+
cmd: 'connack',
|
|
701
|
+
returnCode: 5,
|
|
702
|
+
length: 2,
|
|
703
|
+
qos: 0,
|
|
704
|
+
retain: false,
|
|
705
|
+
dup: false,
|
|
706
|
+
topic: null,
|
|
707
|
+
payload: null,
|
|
708
|
+
sessionPresent: false
|
|
709
|
+
}, 'unsuccessful connack')
|
|
710
|
+
t.assert.equal(s.broker.connectedClients, 0, 'no connected clients')
|
|
711
|
+
await once(s.conn, 'close')
|
|
712
|
+
t.assert.equal(s.conn.closed, true, 's has been disconnected')
|
|
1060
713
|
})
|
|
1061
714
|
|
|
1062
|
-
test('change a topic name inside authorizeForward method in QoS 1 mode',
|
|
715
|
+
test('change a topic name inside authorizeForward method in QoS 1 mode', async (t) => {
|
|
1063
716
|
t.plan(3)
|
|
1064
717
|
|
|
1065
|
-
const broker =
|
|
1066
|
-
authorizeForward:
|
|
718
|
+
const broker = await Aedes.createBroker({
|
|
719
|
+
authorizeForward: (client, packet) => {
|
|
1067
720
|
packet.payload = Buffer.from('another-world')
|
|
1068
721
|
packet.messageId = 2
|
|
1069
722
|
return packet
|
|
1070
723
|
}
|
|
1071
724
|
})
|
|
1072
|
-
t.
|
|
725
|
+
t.after(() => broker.close())
|
|
726
|
+
const s = setup(broker)
|
|
1073
727
|
|
|
1074
728
|
const expected = {
|
|
1075
729
|
cmd: 'publish',
|
|
@@ -1082,96 +736,106 @@ test('change a topic name inside authorizeForward method in QoS 1 mode', functio
|
|
|
1082
736
|
messageId: 2
|
|
1083
737
|
}
|
|
1084
738
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
qos: 1
|
|
1089
|
-
}, function (err) {
|
|
1090
|
-
t.error(err, 'no error')
|
|
1091
|
-
|
|
1092
|
-
broker.publish({
|
|
739
|
+
const publishedOk = new Promise((resolve) => {
|
|
740
|
+
broker.on('client', (client) => {
|
|
741
|
+
client.subscribe({
|
|
1093
742
|
topic: 'hello',
|
|
1094
|
-
payload: Buffer.from('world'),
|
|
1095
743
|
qos: 1
|
|
1096
|
-
},
|
|
1097
|
-
t.
|
|
744
|
+
}, (err) => {
|
|
745
|
+
t.assert.equal(err, undefined, 'no error')
|
|
746
|
+
|
|
747
|
+
broker.publish({
|
|
748
|
+
topic: 'hello',
|
|
749
|
+
payload: Buffer.from('world'),
|
|
750
|
+
qos: 1
|
|
751
|
+
}, (err) => {
|
|
752
|
+
t.assert.equal(err, undefined, 'no error')
|
|
753
|
+
resolve()
|
|
754
|
+
})
|
|
1098
755
|
})
|
|
1099
756
|
})
|
|
1100
757
|
})
|
|
1101
758
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
759
|
+
await Promise.all([
|
|
760
|
+
publishedOk,
|
|
761
|
+
connect(s)
|
|
762
|
+
])
|
|
763
|
+
const packet = await nextPacket(s)
|
|
764
|
+
t.assert.deepEqual(structuredClone(packet), expected, 'packet matches')
|
|
1107
765
|
})
|
|
1108
766
|
|
|
1109
|
-
|
|
1110
|
-
test(`unauthorized forward publish in QoS 1 mode [clean=${cleanSession}]`,
|
|
1111
|
-
t.plan(
|
|
767
|
+
for (const cleanSession of [true, false]) {
|
|
768
|
+
test(`unauthorized forward publish in QoS 1 mode [clean=${cleanSession}]`, async (t) => {
|
|
769
|
+
t.plan(3)
|
|
1112
770
|
|
|
1113
|
-
const broker =
|
|
1114
|
-
authorizeForward:
|
|
771
|
+
const broker = await Aedes.createBroker({
|
|
772
|
+
authorizeForward: (_client, _packet) => {
|
|
1115
773
|
return null
|
|
1116
774
|
}
|
|
1117
775
|
})
|
|
1118
|
-
t.
|
|
1119
|
-
|
|
1120
|
-
broker.on('client', function (client) {
|
|
1121
|
-
client.subscribe({
|
|
1122
|
-
topic: 'hello',
|
|
1123
|
-
qos: 1
|
|
1124
|
-
}, function (err) {
|
|
1125
|
-
t.error(err, 'no error')
|
|
776
|
+
t.after(() => broker.close())
|
|
777
|
+
const s = setup(broker)
|
|
1126
778
|
|
|
1127
|
-
|
|
779
|
+
const publishedOk = new Promise((resolve) => {
|
|
780
|
+
broker.on('client', (client) => {
|
|
781
|
+
client.subscribe({
|
|
1128
782
|
topic: 'hello',
|
|
1129
|
-
payload: Buffer.from('world'),
|
|
1130
783
|
qos: 1
|
|
1131
|
-
},
|
|
1132
|
-
t.
|
|
784
|
+
}, (err) => {
|
|
785
|
+
t.assert.equal(err, undefined, 'no error')
|
|
786
|
+
broker.publish({
|
|
787
|
+
topic: 'hello',
|
|
788
|
+
payload: Buffer.from('world'),
|
|
789
|
+
qos: 1
|
|
790
|
+
}, (err) => {
|
|
791
|
+
t.assert.equal(err, undefined, 'no error')
|
|
792
|
+
resolve()
|
|
793
|
+
})
|
|
1133
794
|
})
|
|
1134
795
|
})
|
|
1135
796
|
})
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
797
|
+
await Promise.all([
|
|
798
|
+
publishedOk,
|
|
799
|
+
connect(s, { connect: { clean: cleanSession } })
|
|
800
|
+
])
|
|
801
|
+
const packet = await nextPacketWithTimeOut(s, 1)
|
|
802
|
+
t.assert.equal(packet, null, 'no packet')
|
|
1142
803
|
})
|
|
1143
|
-
}
|
|
804
|
+
}
|
|
1144
805
|
|
|
1145
|
-
test('prevent publish in QoS 0 mode',
|
|
1146
|
-
t.plan(
|
|
806
|
+
test('prevent publish in QoS 0 mode', async (t) => {
|
|
807
|
+
t.plan(3)
|
|
1147
808
|
|
|
1148
|
-
const broker =
|
|
1149
|
-
authorizeForward:
|
|
809
|
+
const broker = await Aedes.createBroker({
|
|
810
|
+
authorizeForward: (client, packet) => {
|
|
1150
811
|
return null
|
|
1151
812
|
}
|
|
1152
813
|
})
|
|
1153
|
-
t.
|
|
1154
|
-
|
|
1155
|
-
broker.on('client', function (client) {
|
|
1156
|
-
client.subscribe({
|
|
1157
|
-
topic: 'hello',
|
|
1158
|
-
qos: 0
|
|
1159
|
-
}, function (err) {
|
|
1160
|
-
t.error(err, 'no error')
|
|
814
|
+
t.after(() => broker.close())
|
|
815
|
+
const s = setup(broker)
|
|
1161
816
|
|
|
1162
|
-
|
|
817
|
+
const publishedOk = new Promise((resolve) => {
|
|
818
|
+
broker.on('client', (client) => {
|
|
819
|
+
client.subscribe({
|
|
1163
820
|
topic: 'hello',
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
821
|
+
qos: 1
|
|
822
|
+
}, (err) => {
|
|
823
|
+
t.assert.equal(err, undefined, 'no error')
|
|
824
|
+
broker.publish({
|
|
825
|
+
topic: 'hello',
|
|
826
|
+
payload: Buffer.from('world'),
|
|
827
|
+
qos: 1
|
|
828
|
+
}, (err) => {
|
|
829
|
+
t.assert.equal(err, undefined, 'no error')
|
|
830
|
+
resolve()
|
|
831
|
+
})
|
|
1168
832
|
})
|
|
1169
833
|
})
|
|
1170
834
|
})
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
835
|
+
await Promise.all([
|
|
836
|
+
publishedOk,
|
|
837
|
+
connect(s)
|
|
838
|
+
])
|
|
839
|
+
const packet = await nextPacketWithTimeOut(s, 1)
|
|
840
|
+
t.assert.equal(packet, null, 'no packet')
|
|
1177
841
|
})
|