aedes 0.50.1 → 0.51.1

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.
@@ -1,12 +1,13 @@
1
1
  version: 2
2
2
  updates:
3
- - package-ecosystem: github-actions
4
- directory: "/"
5
- schedule:
6
- interval: daily
7
- open-pull-requests-limit: 10
8
- - package-ecosystem: npm
9
- directory: "/"
10
- schedule:
11
- interval: daily
12
- open-pull-requests-limit: 10
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: daily
7
+ open-pull-requests-limit: 10
8
+
9
+ - package-ecosystem: npm
10
+ directory: /
11
+ schedule:
12
+ interval: daily
13
+ open-pull-requests-limit: 10
@@ -1,4 +1,4 @@
1
- name: ci
1
+ name: CI
2
2
 
3
3
  on:
4
4
  push:
@@ -10,33 +10,33 @@ on:
10
10
  - 'docs/**'
11
11
  - '*.md'
12
12
 
13
+ permissions:
14
+ contents: read
15
+
13
16
  jobs:
14
17
  dependency-review:
15
18
  name: Dependency Review
16
19
  if: github.event_name == 'pull_request'
17
20
  runs-on: ubuntu-latest
18
- permissions:
19
- contents: read
20
21
  steps:
21
- - name: Check out repo
22
- uses: actions/checkout@v3
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v4
23
24
  with:
24
25
  persist-credentials: false
25
26
 
26
27
  - name: Dependency review
27
- uses: actions/dependency-review-action@v2
28
+ uses: actions/dependency-review-action@v4
28
29
 
29
30
  test:
30
31
  runs-on: ${{ matrix.os }}
31
- permissions:
32
- contents: read
33
32
  strategy:
34
33
  matrix:
35
34
  node-version: [16, 18, 20]
36
35
  os: [ubuntu-latest, windows-latest, macOS-latest]
37
36
  fail-fast: false
38
37
  steps:
39
- - uses: actions/checkout@v3
38
+ - name: Checkout repository
39
+ uses: actions/checkout@v4
40
40
  with:
41
41
  persist-credentials: false
42
42
 
@@ -45,6 +45,8 @@ jobs:
45
45
  with:
46
46
  node-version: ${{ matrix.node-version }}
47
47
  check-latest: true
48
+ cache: npm
49
+ cache-dependency-path: package.json
48
50
 
49
51
  - name: Install
50
52
  run: |
@@ -68,8 +70,6 @@ jobs:
68
70
  coverage:
69
71
  needs: test
70
72
  runs-on: ubuntu-latest
71
- permissions:
72
- contents: read
73
73
  steps:
74
74
  - name: Coveralls Finished
75
75
  uses: coverallsapp/github-action@master
@@ -1,4 +1,4 @@
1
- name: sast
1
+ name: CodeQL
2
2
 
3
3
  on:
4
4
  push:
@@ -11,19 +11,25 @@ jobs:
11
11
  name: Analyze
12
12
  runs-on: ubuntu-latest
13
13
  permissions:
14
+ actions: read
14
15
  contents: read
15
16
  security-events: write
16
17
  strategy:
17
18
  fail-fast: true
18
19
  matrix:
19
- language: [ 'javascript' ]
20
+ language: [ 'javascript-typescript' ]
20
21
  steps:
21
- - uses: actions/checkout@v3
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v4
22
24
  with:
23
25
  persist-credentials: false
24
26
 
25
- - uses: github/codeql-action/init@v2
27
+ - name: Initialize CodeQL
28
+ uses: github/codeql-action/init@v3
26
29
  with:
27
30
  languages: ${{ matrix.language }}
28
31
 
29
- - uses: github/codeql-action/analyze@v2
32
+ - name: Perform CodeQL Analysis
33
+ uses: github/codeql-action/analyze@v3
34
+ with:
35
+ category: "/language:${{ matrix.language }}"
@@ -1,10 +1,15 @@
1
- name: "Pull Request Labeler"
1
+ name: Pull Request Labeler
2
+
2
3
  on: pull_request_target
3
4
 
5
+ permissions:
6
+ contents: read
7
+ pull-requests: write
8
+
4
9
  jobs:
5
10
  label:
6
11
  runs-on: ubuntu-latest
7
12
  steps:
8
- - uses: actions/labeler@main
9
- with:
10
- repo-token: "${{ secrets.GITHUB_TOKEN }}"
13
+ - uses: actions/labeler@v5
14
+ with:
15
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
package/README.md CHANGED
@@ -1,12 +1,10 @@
1
- <!-- markdownlint-disable MD013 MD024 -->
1
+ <!-- markdownlint-disable MD013 -->
2
2
  # Aedes
3
3
 
4
4
  ![ci](https://github.com/moscajs/aedes/workflows/ci/badge.svg)
5
- [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
5
+ [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
6
6
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/moscajs/aedes/graphs/commit-activity)
7
7
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/moscajs/aedes/pulls)\
8
- [![Total alerts](https://img.shields.io/lgtm/alerts/g/moscajs/aedes.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/moscajs/aedes/alerts/)
9
- [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/moscajs/aedes.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/moscajs/aedes/context:javascript)
10
8
  [![Coverage Status](https://coveralls.io/repos/moscajs/aedes/badge.svg?branch=main&service=github)](https://coveralls.io/github/moscajs/aedes?branch=main)
11
9
  [![Known Vulnerabilities](https://snyk.io/test/github/moscajs/aedes/badge.svg)](https://snyk.io/test/github/moscajs/aedes)\
12
10
  ![node](https://img.shields.io/node/v/aedes)
@@ -283,7 +281,7 @@ Want to contribute? Check our list of
283
281
 
284
282
  ## Security notice
285
283
 
286
- Messages sent to the broker are considered _valid_ once they pass the [`authorizePublish`](https://github.com/moscajs/aedes/blob/main/docs/Aedes.md#handler-authorizepublish-client-packet-callback) callback.
284
+ Messages sent to the broker are considered _valid_ once they pass the [`authorizePublish`](./docs/Aedes.md#handler-authorizepublish-client-packet-callback) callback.
287
285
  In other terms, if permissions for the given client are revoked after the call completes, the message is still considered valid.
288
286
  In case you are sending time-sensitive messages, make sure to use QoS 0 or connect with a clean session.
289
287
 
package/SECURITY.md CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  ## Reporting a Vulnerability
4
4
 
5
- Please email daniel.sorridi+aedes@gmail.com; matteo.collina+aedes@gmail.com
5
+ Please report all vulnerabilities to [https://github.com/moscajs/aedes/security](https://github.com/moscajs/aedes/security).
package/aedes.js CHANGED
@@ -29,7 +29,8 @@ const defaultOptions = {
29
29
  trustProxy: false,
30
30
  trustedProxies: [],
31
31
  queueLimit: 42,
32
- maxClientsIdLength: 23
32
+ maxClientsIdLength: 23,
33
+ keepaliveLimit: 0
33
34
  }
34
35
 
35
36
  function Aedes (opts) {
@@ -47,6 +48,7 @@ function Aedes (opts) {
47
48
  this.counter = 0
48
49
  this.queueLimit = opts.queueLimit
49
50
  this.connectTimeout = opts.connectTimeout
51
+ this.keepaliveLimit = opts.keepaliveLimit
50
52
  this.maxClientsIdLength = opts.maxClientsIdLength
51
53
  this.mq = opts.mq || mqemitter({
52
54
  concurrency: opts.concurrency,
@@ -168,7 +170,13 @@ function Aedes (opts) {
168
170
  const clientId = packet.payload.toString()
169
171
 
170
172
  if (that.clients[clientId] && serverId !== that.id) {
171
- that.clients[clientId].close(done)
173
+ if (that.clients[clientId].closed) {
174
+ // remove the client from the list if it is already closed
175
+ delete that.clients[clientId]
176
+ done()
177
+ } else {
178
+ that.clients[clientId].close(done)
179
+ }
172
180
  } else {
173
181
  done()
174
182
  }
package/docs/Aedes.md CHANGED
@@ -42,6 +42,7 @@
42
42
  - `heartbeatInterval` `<number>` an interval in millisconds at which server beats its health signal in `$SYS/<aedes.id>/heartbeat` topic. __Default__: `60000`
43
43
  - `id` `<string>` aedes broker unique identifier. __Default__: `uuidv4()`
44
44
  - `connectTimeout` `<number>` maximum waiting time in milliseconds waiting for a [`CONNECT`][CONNECT] packet. __Default__: `30000`
45
+ - `keepaliveLimit` `<number>` maximum client keep alive time allowed, 0 means no limit. __Default__: `0`
45
46
  - Returns `<Aedes>`
46
47
 
47
48
  Create a new Aedes server.
@@ -36,7 +36,8 @@ const errorMessages = [
36
36
  'identifier rejected',
37
37
  'Server unavailable',
38
38
  'bad user name or password',
39
- 'not authorized'
39
+ 'not authorized',
40
+ 'keep alive limit exceeded'
40
41
  ]
41
42
 
42
43
  function handleConnect (client, packet, done) {
@@ -66,6 +67,10 @@ function init (client, packet, done) {
66
67
  if (packet.protocolVersion === 3 && clientId.length > client.broker.maxClientsIdLength) {
67
68
  returnCode = 2
68
69
  }
70
+ // check if the client keepalive is compatible with broker settings
71
+ if (client.broker.keepaliveLimit && (!packet.keepalive || packet.keepalive > client.broker.keepaliveLimit)) {
72
+ returnCode = 6
73
+ }
69
74
  if (returnCode > 0) {
70
75
  const error = new Error(errorMessages[returnCode])
71
76
  error.errorCode = returnCode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aedes",
3
- "version": "0.50.1",
3
+ "version": "0.51.1",
4
4
  "description": "Stream-based MQTT broker",
5
5
  "main": "aedes.js",
6
6
  "types": "aedes.d.ts",
@@ -16,7 +16,7 @@
16
16
  "test:typescript": "tsd",
17
17
  "unit": "tap -J test/*.js",
18
18
  "unit:report": "tap -J test/*.js --cov --coverage-report=html --coverage-report=cobertura | tee out.tap",
19
- "license-checker": "license-checker --production --onlyAllow=\"MIT;ISC;BSD-3-Clause;BSD-2-Clause\"",
19
+ "license-checker": "license-checker --production --onlyAllow=\"MIT;ISC;BSD-3-Clause;BSD-2-Clause;0BSD\"",
20
20
  "release": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it --disable-metrics"
21
21
  },
22
22
  "release-it": {
@@ -89,6 +89,10 @@
89
89
  }
90
90
  ],
91
91
  "license": "MIT",
92
+ "funding": {
93
+ "type": "opencollective",
94
+ "url": "https://opencollective.com/aedes"
95
+ },
92
96
  "bugs": {
93
97
  "url": "https://github.com/moscajs/aedes/issues"
94
98
  },
@@ -97,24 +101,24 @@
97
101
  "node": ">=16"
98
102
  },
99
103
  "devDependencies": {
100
- "@sinonjs/fake-timers": "^10.3.0",
101
- "@types/node": "^20.4.5",
102
- "@typescript-eslint/eslint-plugin": "^6.2.0",
103
- "@typescript-eslint/parser": "^6.2.0",
104
+ "@sinonjs/fake-timers": "^11.2.2",
105
+ "@types/node": "^20.11.17",
106
+ "@typescript-eslint/eslint-plugin": "^7.0.1",
107
+ "@typescript-eslint/parser": "^7.0.1",
104
108
  "concat-stream": "^2.0.0",
105
109
  "duplexify": "^4.1.2",
106
110
  "license-checker": "^25.0.1",
107
- "markdownlint-cli": "^0.35.0",
108
- "mqtt": "^5.0.0",
111
+ "markdownlint-cli": "^0.39.0",
112
+ "mqtt": "^5.3.5",
109
113
  "mqtt-connection": "^4.1.0",
110
114
  "pre-commit": "^1.2.2",
111
115
  "proxyquire": "^2.1.3",
112
- "release-it": "^16.1.3",
116
+ "release-it": "^17.0.5",
113
117
  "snazzy": "^9.0.0",
114
118
  "standard": "^17.1.0",
115
- "tap": "^16.3.7",
116
- "tsd": "^0.28.1",
117
- "typescript": "^5.1.6",
119
+ "tap": "^16.3.10",
120
+ "tsd": "^0.30.4",
121
+ "typescript": "^5.3.3",
118
122
  "websocket-stream": "^5.5.2"
119
123
  },
120
124
  "dependencies": {
@@ -124,11 +128,11 @@
124
128
  "fastfall": "^1.5.1",
125
129
  "fastparallel": "^2.4.1",
126
130
  "fastseries": "^2.0.0",
127
- "hyperid": "^3.1.1",
131
+ "hyperid": "^3.2.0",
128
132
  "mqemitter": "^5.0.0",
129
133
  "mqtt-packet": "^9.0.0",
130
- "retimer": "^3.0.0",
134
+ "retimer": "^4.0.0",
131
135
  "reusify": "^1.0.4",
132
- "uuid": "^9.0.0"
136
+ "uuid": "^9.0.1"
133
137
  }
134
138
  }
package/test/connect.js CHANGED
@@ -97,6 +97,40 @@ test('reject client requested for unsupported protocol version', function (t) {
97
97
  })
98
98
  })
99
99
 
100
+ test('reject clients that exceed the keepalive limit', function (t) {
101
+ t.plan(3)
102
+
103
+ const broker = aedes({
104
+ keepaliveLimit: 100
105
+ })
106
+ t.teardown(broker.close.bind(broker))
107
+
108
+ const s = setup(broker)
109
+
110
+ s.inStream.write({
111
+ cmd: 'connect',
112
+ keepalive: 150
113
+ })
114
+ s.outStream.on('data', function (packet) {
115
+ console.log(packet)
116
+ t.same(packet, {
117
+ cmd: 'connack',
118
+ returnCode: 6,
119
+ length: 2,
120
+ qos: 0,
121
+ retain: false,
122
+ dup: false,
123
+ topic: null,
124
+ payload: null,
125
+ sessionPresent: false
126
+ }, 'unsuccessful connack, keep alive limit exceeded')
127
+ })
128
+ broker.on('connectionError', function (client, err) {
129
+ t.equal(err.message, 'keep alive limit exceeded')
130
+ t.equal(broker.connectedClients, 0)
131
+ })
132
+ })
133
+
100
134
  // Guarded in mqtt-packet
101
135
  test('reject clients with no clientId running on MQTT 3.1.0', function (t) {
102
136
  t.plan(3)
package/test/events.js CHANGED
@@ -221,3 +221,20 @@ test('Test backpressure aedes published function', function (t) {
221
221
  })
222
222
  })
223
223
  })
224
+
225
+ test('clear closed clients when the same clientId is managed by another broker', function (t) {
226
+ t.plan(1)
227
+
228
+ const clientId = 'closed-client'
229
+ const broker = aedes()
230
+
231
+ // simulate a closed client on the broker
232
+ broker.clients[clientId] = { closed: true }
233
+
234
+ // simulate the creation of the same client on another broker of the cluster
235
+ broker.publish({ topic: '$SYS/anotherbroker/new/clients', payload: clientId }, () => {
236
+ t.equal(broker.clients[clientId], undefined) // check that the closed client was removed
237
+ })
238
+
239
+ t.teardown(broker.close.bind(broker))
240
+ })
@@ -23,6 +23,7 @@ broker = new Aedes({
23
23
  heartbeatInterval: 60000,
24
24
  connectTimeout: 30000,
25
25
  maxClientsIdLength: 23,
26
+ keepaliveLimit: 0,
26
27
  preConnect: (client: Client, packet: ConnectPacket, callback) => {
27
28
  if (client.req) {
28
29
  callback(new Error('not websocket stream'), false)
@@ -75,6 +75,7 @@ export interface AedesOptions {
75
75
  concurrency?: number;
76
76
  heartbeatInterval?: number;
77
77
  connectTimeout?: number;
78
+ keepaliveLimit?: number;
78
79
  queueLimit?: number;
79
80
  maxClientsIdLength?: number;
80
81
  preConnect?: PreConnectHandler;