Skip to content

Commit fa19586

Browse files
fix: add option to reconnect if connack has an error code (#1948)
Co-authored-by: Daniel Lando <[email protected]>
1 parent b5b0967 commit fa19586

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,13 @@ the final connection when it drops.
275275
The default value is 1000 ms which means it will try to reconnect 1 second
276276
after losing the connection.
277277

278+
Note that this will only enable reconnects after either a connection timeout, or
279+
after a successful connection. It will _not_ (by default) enable retrying
280+
connections that are actively denied with a CONNACK error by the server.
281+
282+
To also enable automatic reconnects for CONNACK errors, set
283+
`reconnectOnConnackError: true`.
284+
278285
<a name="topicalias"></a>
279286

280287
## About Topic Alias Management
@@ -415,6 +422,8 @@ The arguments are:
415422
offline
416423
- `reconnectPeriod`: `1000` milliseconds, interval between two
417424
reconnections. Disable auto reconnect by setting to `0`.
425+
- `reconnectOnConnackError`: `false`, whether to also reconnect if a CONNACK
426+
is received with an error.
418427
- `connectTimeout`: `30 * 1000` milliseconds, time to wait before a
419428
CONNACK is received
420429
- `username`: the username required by your broker, if any

src/lib/client.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ export interface IClientOptions extends ISecureClientOptions {
162162
* 1000 milliseconds, interval between two reconnections
163163
*/
164164
reconnectPeriod?: number
165+
/**
166+
* Set to true to enable the reconnect period to apply if the initial
167+
* connection is denied with an error in the CONNACK packet, such as with an
168+
* authentication error.
169+
*/
170+
reconnectOnConnackError?: boolean
165171
/**
166172
* 30 * 1000 milliseconds, time to wait before a CONNACK is received
167173
*/

src/lib/handlers/connack.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ const handleConnack: PacketHandler = (client, packet: IConnackPacket) => {
4949
rc,
5050
)
5151
client.emit('error', err)
52+
if (client.options.reconnectOnConnackError) {
53+
client['_cleanUp'](true)
54+
}
5255
}
5356
}
5457

test/node/abstract_client.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,6 +3335,42 @@ export default function abstractTest(server, config, ports) {
33353335
})
33363336
})
33373337

3338+
it('should reconnect on connack error if requested', function _test(t, done) {
3339+
let connackErrors = 0
3340+
const rcNotAuthorized = 135
3341+
const server2 = serverBuilder(config.protocol, (serverClient) => {
3342+
serverClient.on('connect', () => {
3343+
const rc = connackErrors === 0 ? rcNotAuthorized : 0
3344+
const connack =
3345+
version === 5 ? { reasonCode: rc } : { returnCode: rc }
3346+
serverClient.connack(connack)
3347+
})
3348+
})
3349+
teardownHelper.addServer(server2)
3350+
server2.listen(ports.PORTAND50, () => {
3351+
const client = connect({
3352+
host: 'localhost',
3353+
port: ports.PORTAND50,
3354+
reconnectPeriod: 10,
3355+
reconnectOnConnackError: true,
3356+
})
3357+
teardownHelper.addClient(client)
3358+
client.on('error', (err) => {
3359+
assert.instanceOf(err, ErrorWithReasonCode)
3360+
assert.equal(
3361+
(err as ErrorWithReasonCode).code,
3362+
rcNotAuthorized,
3363+
)
3364+
assert.equal(connackErrors, 0)
3365+
connackErrors++
3366+
})
3367+
client.on('connect', () => {
3368+
assert.equal(connackErrors, 1)
3369+
done()
3370+
})
3371+
})
3372+
})
3373+
33383374
it(
33393375
'should resend in-flight QoS 1 publish messages from the client',
33403376
{

0 commit comments

Comments
 (0)