Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f6387a8
fix(types): added module declaration (#879)
peeveen Jul 24, 2023
d0507b6
chore(deps-dev): bump mqtt from 4.3.7 to 5.0.0 (#882)
dependabot[bot] Jul 26, 2023
46af8e6
chore(deps): bump deps
robertsLando Jul 26, 2023
ee1f63b
chore!: drop node14 support
robertsLando Jul 26, 2023
c9bddd3
Release 0.50.0
robertsLando Jul 26, 2023
bebf8af
chore(deps): bump actions/setup-node from 3 to 4
dependabot[bot] Oct 24, 2023
3180f2a
chore(deps): bump mqtt-packet from 8.2.1 to 9.0.0
dependabot[bot] Nov 8, 2023
6662b37
fix(types): module exports for TypeScript for ES6 compliance. (#918)
hjdhjd Dec 8, 2023
981d071
Release 0.50.1
robertsLando Dec 11, 2023
f625f1b
chore(deps): bump github/codeql-action from 2 to 3 (#922)
dependabot[bot] Dec 14, 2023
e1ee60c
feat: add `opts.keepaliveLimit` (#930)
Gianluca-Casagrande-Stiga Jan 12, 2024
f42882c
fix: delete already closed client on closeSameClients (#929)
Gianluca-Casagrande-Stiga Jan 12, 2024
f5e6d0e
Release 0.51.0
robertsLando Jan 12, 2024
c75240a
chore: update README.md
gnought Feb 15, 2024
af96ae9
chore(deps): bump deps
gnought Feb 15, 2024
dcf95f5
chore: update allowed license, add funding
gnought Feb 15, 2024
f98105e
chore: update workflows
gnought Feb 15, 2024
bba422b
chore: update SECURITY.md
gnought Feb 15, 2024
ac4f2e0
fix: remove console.error (#951) (#952)
simonnilsson May 7, 2024
1047619
Release 0.51.1
robertsLando May 7, 2024
86e85f5
chore(deps): bump mqemitter from 5.0.0 to 6.0.0 (#953)
dependabot[bot] May 7, 2024
c7abeda
chore(deps-dev): bump markdownlint-cli from 0.39.0 to 0.40.0 (#950)
dependabot[bot] May 15, 2024
27218ed
chore(deps-dev): bump markdownlint-cli from 0.40.0 to 0.41.0 (#956)
dependabot[bot] May 30, 2024
1bbff52
chore(deps-dev): bump tsd from 0.30.7 to 0.31.0 (#947)
dependabot[bot] May 30, 2024
a26b90b
fix: delete will from persistence on disconnect (#957)
bmeverett Jun 7, 2024
213d123
Release 0.51.2
robertsLando Jun 7, 2024
1a191b0
chore(deps): bump uuid from 9.0.1 to 10.0.0 (#958)
dependabot[bot] Jun 10, 2024
9b9d524
fix: memory leak in connected clients counter (#979)
uladzimir-danko Aug 28, 2024
d0c4414
Release 0.51.3
robertsLando Aug 28, 2024
a63e387
feat: upgrade aedes dependencies to 0.50.0
rajathongal-intangles Mar 11, 2026
7ee32c1
feat: merge upstream v0.51.3 and add OTel instrumentation compatibility
rajathongal-intangles Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
open-pull-requests-limit: 10

- package-ecosystem: npm
directory: /
schedule:
interval: daily
open-pull-requests-limit: 10
27 changes: 14 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ci
name: CI

on:
push:
Expand All @@ -10,40 +10,43 @@ on:
- 'docs/**'
- '*.md'

permissions:
contents: read

jobs:
dependency-review:
name: Dependency Review
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out repo
uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Dependency review
uses: actions/dependency-review-action@v2
uses: actions/dependency-review-action@v4

test:
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
matrix:
node-version: [14, 16, '*']
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest, macOS-latest]
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Use Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
check-latest: true
cache: npm
cache-dependency-path: package.json

- name: Install
run: |
Expand All @@ -67,8 +70,6 @@ jobs:
coverage:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
Expand Down
16 changes: 11 additions & 5 deletions .github/workflows/sast.yml → .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: sast
name: CodeQL

on:
push:
Expand All @@ -11,19 +11,25 @@ jobs:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: true
matrix:
language: [ 'javascript' ]
language: [ 'javascript-typescript' ]
steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- uses: github/codeql-action/init@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}

- uses: github/codeql-action/analyze@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
13 changes: 9 additions & 4 deletions .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
name: "Pull Request Labeler"
name: Pull Request Labeler

on: pull_request_target

permissions:
contents: read
pull-requests: write

jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<!-- markdownlint-disable MD013 MD024 -->
<!-- markdownlint-disable MD013 -->
# Aedes

![ci](https://github.com/moscajs/aedes/workflows/ci/badge.svg)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/moscajs/aedes/graphs/commit-activity)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/moscajs/aedes/pulls)\
[![Total alerts](https://img.shields.io/lgtm/alerts/g/moscajs/aedes.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/moscajs/aedes/alerts/)
[![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)
[![Coverage Status](https://coveralls.io/repos/moscajs/aedes/badge.svg?branch=main&service=github)](https://coveralls.io/github/moscajs/aedes?branch=main)
[![Known Vulnerabilities](https://snyk.io/test/github/moscajs/aedes/badge.svg)](https://snyk.io/test/github/moscajs/aedes)\
![node](https://img.shields.io/node/v/aedes)
Expand Down Expand Up @@ -283,7 +281,7 @@ Want to contribute? Check our list of

## Security notice

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.
Messages sent to the broker are considered _valid_ once they pass the [`authorizePublish`](./docs/Aedes.md#handler-authorizepublish-client-packet-callback) callback.
In other terms, if permissions for the given client are revoked after the call completes, the message is still considered valid.
In case you are sending time-sensitive messages, make sure to use QoS 0 or connect with a clean session.

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

## Reporting a Vulnerability

Please email daniel.sorridi+aedes@gmail.com; matteo.collina+aedes@gmail.com
Please report all vulnerabilities to [https://github.com/moscajs/aedes/security](https://github.com/moscajs/aedes/security).
6 changes: 5 additions & 1 deletion aedes.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import Aedes, { AedesOptions } from './types/instance'

export declare function createBroker (options?: AedesOptions): Aedes
export declare function createBroker(options?: AedesOptions): Aedes

export * from './types/instance'
export * from './types/packet'
export * from './types/client'
export default Aedes

declare module 'aedes' {
export = Aedes
}
67 changes: 53 additions & 14 deletions aedes.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
authorizeSubscribe: defaultAuthorizeSubscribe,
authorizeForward: defaultAuthorizeForward,
published: defaultPublished,
wrapDeliveryFunc: null,
trustProxy: false,
trustedProxies: [],
queueLimit: 42,
maxClientsIdLength: 23
maxClientsIdLength: 23,
keepaliveLimit: 0
}

function Aedes (opts) {
Expand All @@ -47,29 +49,26 @@
this.counter = 0
this.queueLimit = opts.queueLimit
this.connectTimeout = opts.connectTimeout
this.keepaliveLimit = opts.keepaliveLimit
this.maxClientsIdLength = opts.maxClientsIdLength
this.mq = opts.mq || mqemitter({
concurrency: opts.concurrency,
matchEmptyLevels: true // [MQTT-4.7.1-3]
})
this.handle = function handle (conn, req) {
conn.setMaxListeners(opts.concurrency * 2)
// create a new Client instance for a new connection
// return, just to please standard
return new Client(that, conn, req)
}
this.concurrency = opts.concurrency
this.persistence = opts.persistence || memory()
this.persistence.broker = this
this._parallel = parallel()
this._series = series()
this._enqueuers = reusify(DoEnqueues)

this.preConnect = opts.preConnect
this.authenticate = opts.authenticate
this.authorizePublish = opts.authorizePublish
this.authorizeSubscribe = opts.authorizeSubscribe
this._preConnect = opts.preConnect
this._authenticate = opts.authenticate
this._authorizePublish = opts.authorizePublish
this._authorizeSubscribe = opts.authorizeSubscribe
this.authorizeForward = opts.authorizeForward
this.published = opts.published
this._wrapDeliveryFunc = opts.wrapDeliveryFunc

this.decodeProtocol = opts.decodeProtocol
this.trustProxy = opts.trustProxy
Expand Down Expand Up @@ -168,7 +167,13 @@
const clientId = packet.payload.toString()

if (that.clients[clientId] && serverId !== that.id) {
that.clients[clientId].close(done)
if (that.clients[clientId].closed) {
// remove the client from the list if it is already closed
that.deleteClient(clientId)
done()
} else {
that.clients[clientId].close(done)
}
} else {
done()
}
Expand All @@ -181,6 +186,36 @@

util.inherits(Aedes, EventEmitter)

Aedes.prototype.handle = function handle (conn, req) {
conn.setMaxListeners(this.concurrency * 2)
// create a new Client instance for a new connection
// return, just to please standard
return new Client(this, conn, req)
}

Aedes.prototype.preConnect = function preConnect (client, packet, callback) {
this._preConnect(client, packet, callback)
}

Aedes.prototype.authenticate = function authenticate (client, username, password, callback) {
this._authenticate(client, username, password, callback)
}

Aedes.prototype.authorizePublish = function authorizePublish (client, packet, callback) {
this._authorizePublish(client, packet, callback)
}

Aedes.prototype.authorizeSubscribe = function authorizeSubscribe (client, sub, callback) {
this._authorizeSubscribe(client, sub, callback)
}

Aedes.prototype.wrapDeliveryFunc = function wrapDeliveryFunc (client, func) {
if (this._wrapDeliveryFunc) {
return this._wrapDeliveryFunc(client, func)
}
return func
}

function storeRetained (packet, done) {
if (packet.retain) {
this.broker.persistence.storeRetained(packet, done)
Expand All @@ -198,8 +233,8 @@
} else {
if (process.env.SUPPRESS_MQTT_EVENTS === '1') {
if (
!/^\$SYS\/.*\/new\/subscribes$/gm.test(packet.topic) &&

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, windows-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, windows-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, macOS-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, windows-latest)

Trailing spaces not allowed

Check failure on line 236 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, windows-latest)

Trailing spaces not allowed
!/^\$SYS\/.*\/new\/clients$/gm.test(packet.topic) &&

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, ubuntu-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, windows-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (18, windows-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, macOS-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, windows-latest)

Trailing spaces not allowed

Check failure on line 237 in aedes.js

View workflow job for this annotation

GitHub Actions / test (16, windows-latest)

Trailing spaces not allowed
!/^\$SYS\/.*\/disconnect\/clients$/gm.test(packet.topic) &&
!/^\$SYS\/.*\/new\/unsubscribes$/gm.test(packet.topic)
) {
Expand Down Expand Up @@ -326,15 +361,19 @@
}

Aedes.prototype.unregisterClient = function (client) {
this.connectedClients--
delete this.clients[client.id]
this.deleteClient(client.id)
this.emit('clientDisconnect', client)
this.publish({
topic: $SYS_PREFIX + this.id + '/disconnect/clients',
payload: Buffer.from(client.id, 'utf8')
}, noop)
}

Aedes.prototype.deleteClient = function (clientId) {
this.connectedClients--
delete this.clients[clientId]
}

function closeClient (client, cb) {
this.clients[client].close(cb)
}
Expand Down
1 change: 1 addition & 0 deletions docs/Aedes.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- `heartbeatInterval` `<number>` an interval in millisconds at which server beats its health signal in `$SYS/<aedes.id>/heartbeat` topic. __Default__: `60000`
- `id` `<string>` aedes broker unique identifier. __Default__: `uuidv4()`
- `connectTimeout` `<number>` maximum waiting time in milliseconds waiting for a [`CONNECT`][CONNECT] packet. __Default__: `30000`
- `keepaliveLimit` `<number>` maximum client keep alive time allowed, 0 means no limit. __Default__: `0`
- Returns `<Aedes>`

Create a new Aedes server.
Expand Down
15 changes: 11 additions & 4 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ const EventEmitter = require('events')
const util = require('util')
const eos = require('end-of-stream')
const Packet = require('aedes-packet')
const write = require('./write')
const { write } = require('./write')
const QoSPacket = require('./qos-packet')
const handleSubscribe = require('./handlers/subscribe')
const handleUnsubscribe = require('./handlers/unsubscribe')
const handle = require('./handlers')
const { handleSubscribe } = require('./handlers/subscribe')
const { handleUnsubscribe } = require('./handlers/unsubscribe')
const { handle } = require('./handlers')
const { pipeline } = require('stream')
const { through } = require('./utils')

Expand Down Expand Up @@ -313,7 +313,14 @@ Client.prototype.close = function (done) {
}, noop)
}
})
} else if (will) {
// delete the persisted will even on clean disconnect https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349232
that.broker.persistence.delWill({
id: that.id,
brokerId: that.broker.id
}, noop)
}

that.will = null // this function might be called twice
that._will = null

Expand Down
13 changes: 9 additions & 4 deletions lib/handlers/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

const retimer = require('retimer')
const { pipeline } = require('stream')
const write = require('../write')
const { write } = require('../write')
const QoSPacket = require('../qos-packet')
const { through } = require('../utils')
const handleSubscribe = require('./subscribe')
const { handleSubscribe } = require('./subscribe')
const uniqueId = require('hyperid')()

function Connack (arg) {
Expand Down Expand Up @@ -36,7 +36,8 @@ const errorMessages = [
'identifier rejected',
'Server unavailable',
'bad user name or password',
'not authorized'
'not authorized',
'keep alive limit exceeded'
]

function handleConnect (client, packet, done) {
Expand Down Expand Up @@ -66,6 +67,10 @@ function init (client, packet, done) {
if (packet.protocolVersion === 3 && clientId.length > client.broker.maxClientsIdLength) {
returnCode = 2
}
// check if the client keepalive is compatible with broker settings
if (client.broker.keepaliveLimit && (!packet.keepalive || packet.keepalive > client.broker.keepaliveLimit)) {
returnCode = 6
}
if (returnCode > 0) {
const error = new Error(errorMessages[returnCode])
error.errorCode = returnCode
Expand Down Expand Up @@ -264,4 +269,4 @@ function emptyQueueFilter (err, client, packet) {
}
}

module.exports = handleConnect
module.exports = { handleConnect }
Loading
Loading