Initial commit

This commit is contained in:
2025-12-07 14:32:46 +00:00
commit 0a0969b8af
4726 changed files with 536089 additions and 0 deletions

27
node_modules/mqtt-packet/.github/workflows/ci.yml generated vendored Executable file
View File

@@ -0,0 +1,27 @@
name: ci
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install
run: |
npm install
- name: Run tests
run: |
npm run ci

27
node_modules/mqtt-packet/CONTRIBUTING.md generated vendored Executable file
View File

@@ -0,0 +1,27 @@
# mqtt-packet is an OPEN Open Source Project
-----------------------------------------
## What?
Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
## Rules
There are a few basic ground-rules for contributors:
1. **No `--force` pushes** or modifying the Git history in any way.
1. **Non-master branches** ought to be used for ongoing work.
1. **External API changes and significant modifications** ought to be subject to an **internal pull-request** to solicit feedback from other contributors.
1. Internal pull-requests to solicit feedback are *encouraged* for any other non-trivial contribution but left to the discretion of the contributor.
1. Contributors should attempt to adhere to the prevailing code-style.
## Releases
Declaring formal releases remains the prerogative of the project maintainer.
## Changes to this arrangement
This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change.
-----------------------------------------

13
node_modules/mqtt-packet/LICENSE.md generated vendored Executable file
View File

@@ -0,0 +1,13 @@
The MIT License (MIT)
=====================
Copyright (c) 2014-2017 mqtt-packet contributors
---------------------------------------
*mqtt-packet contributors listed at <https://github.com/mqttjs/mqtt-packet#contributors>*
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

491
node_modules/mqtt-packet/README.md generated vendored Executable file
View File

@@ -0,0 +1,491 @@
mqtt-packet
===========
Encode and Decode MQTT 3.1.1, 5.0 packets the node way.
[![JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
* <a href="#installation">Installation</a>
* <a href="#examples">Examples</a>
* <a href="#packets">Packets</a>
* <a href="#api">API</a>
* <a href="#contributing">Contributing</a>
* <a href="#license">License &amp; copyright</a>
This library is tested with node v6, v8, v10, v12 and v14. The last version to support
older versions of node was mqtt-packet@4.1.2.
Installation
------------
```bash
npm install mqtt-packet --save
```
Examples
--------
### Generating
```js
const mqtt = require('mqtt-packet');
const object = {
cmd: 'publish',
retain: false,
qos: 0,
dup: false,
length: 10,
topic: 'test',
payload: 'test' // Can also be a Buffer
};
const opts = { protocolVersion: 4 }; // default is 4. Usually, opts is a connect packet
console.log(mqtt.generate(object))
// Prints:
//
// <Buffer 30 0a 00 04 74 65 73 74 74 65 73 74>
//
// Which is the same as:
//
// Buffer.from([
// 48, 10, // Header (publish)
// 0, 4, // Topic length
// 116, 101, 115, 116, // Topic (test)
// 116, 101, 115, 116 // Payload (test)
// ])
```
### Parsing
```js
const mqtt = require('mqtt-packet');
const opts = { protocolVersion: 4 }; // default is 4. Usually, opts is a connect packet
const parser = mqtt.parser(opts);
// Synchronously emits all the parsed packets
parser.on('packet', packet => {
console.log(packet)
// Prints:
//
// {
// cmd: 'publish',
// retain: false,
// qos: 0,
// dup: false,
// length: 10,
// topic: 'test',
// payload: <Buffer 74 65 73 74>
// }
})
parser.parse(Buffer.from([
48, 10, // Header (publish)
0, 4, // Topic length
116, 101, 115, 116, // Topic (test)
116, 101, 115, 116 // Payload (test)
]))
// Returns the number of bytes left in the parser
```
API
---
* <a href="#generate"><code>mqtt#<b>generate()</b></code></a>
* <a href="#writeToStream"><code>mqtt#<b>writeToStream()</b></code></a>
* <a href="#parser"><code>mqtt#<b>parser()</b></code></a>
<a name="generate">
### mqtt.generate(object, [opts])
Generates a `Buffer` containing an MQTT packet.
The object must be one of the ones specified by the [packets](#packets)
section. Throws an `Error` if a packet cannot be generated.
<a name="writeToStream">
### mqtt.writeToStream(object, stream, [opts])
Writes the mqtt packet defined by `object` to the given stream.
The object must be one of the ones specified by the [packets](#packets)
section. Emits an `Error` on the stream if a packet cannot be generated.
On node >= 0.12, this function automatically calls `cork()` on your stream,
and then it calls `uncork()` on the next tick.
By default cache for number buffers is enabled.
It creates a list of buffers for faster write. To disable cache set `mqtt.writeToStream.cacheNumbers = false`.
Should be set before any `writeToStream` calls.
<a name="parser">
### mqtt.parser([opts])
Returns a new `Parser` object. `Parser` inherits from `EventEmitter` and
will emit:
* `packet`, when a new packet is parsed, according to
[packets](#packets)
* `error`, if an error happens
<a name="parse">
#### Parser.parse(buffer)
Parses a given `Buffer` and emits synchronously all the MQTT packets that
are included. Returns the number of bytes left to parse.
If an error happens, an `error` event will be emitted, but no `packet` events
will be emitted after that. Calling `parse()` again clears the error and
previous buffer, as if you created a new `Parser`.
Packets
-------
This section describes the format of all packets emitted by the `Parser`
and that you can input to `generate`.
### Connect
```js
{
cmd: 'connect',
protocolId: 'MQTT', // Or 'MQIsdp' in MQTT 3.1 and 5.0
protocolVersion: 4, // Or 3 in MQTT 3.1, or 5 in MQTT 5.0
clean: true, // Can also be false
clientId: 'my-device',
keepalive: 0, // Seconds which can be any positive number, with 0 as the default setting
username: 'matteo',
password: Buffer.from('collina'), // Passwords are buffers
will: {
topic: 'mydevice/status',
payload: Buffer.from('dead'), // Payloads are buffers
properties: { // MQTT 5.0
willDelayInterval: 1234,
payloadFormatIndicator: false,
messageExpiryInterval: 4321,
contentType: 'test',
responseTopic: 'topic',
correlationData: Buffer.from([1, 2, 3, 4]),
userProperties: {
'test': 'test'
}
}
},
properties: { // MQTT 5.0 properties
sessionExpiryInterval: 1234,
receiveMaximum: 432,
maximumPacketSize: 100,
topicAliasMaximum: 456,
requestResponseInformation: true,
requestProblemInformation: true,
userProperties: {
'test': 'test'
},
authenticationMethod: 'test',
authenticationData: Buffer.from([1, 2, 3, 4])
}
}
```
If `protocolVersion` is 3, `clientId` is mandatory and `generate` will throw if
missing.
If `password` or `will.payload` are passed as strings, they will
automatically be converted into a `Buffer`.
### Connack
```js
{
cmd: 'connack',
returnCode: 0, // Or whatever else you see fit MQTT < 5.0
sessionPresent: false, // Can also be true.
reasonCode: 0, // reason code MQTT 5.0
properties: { // MQTT 5.0 properties
sessionExpiryInterval: 1234,
receiveMaximum: 432,
maximumQoS: 1,
retainAvailable: true,
maximumPacketSize: 100,
assignedClientIdentifier: 'test',
topicAliasMaximum: 456,
reasonString: 'test',
userProperties: {
'test': 'test'
},
wildcardSubscriptionAvailable: true,
subscriptionIdentifiersAvailable: true,
sharedSubscriptionAvailable: false,
serverKeepAlive: 1234,
responseInformation: 'test',
serverReference: 'test',
authenticationMethod: 'test',
authenticationData: Buffer.from([1, 2, 3, 4])
}
}
```
The only mandatory argument is `returnCode`, as `generate` will throw if
missing.
### Subscribe
```js
{
cmd: 'subscribe',
messageId: 42,
properties: { // MQTT 5.0 properties
subscriptionIdentifier: 145,
userProperties: {
test: 'test'
}
}
subscriptions: [{
topic: 'test',
qos: 0,
nl: false, // no Local MQTT 5.0 flag
rap: true, // Retain as Published MQTT 5.0 flag
rh: 1 // Retain Handling MQTT 5.0
}]
}
```
All properties are mandatory.
### Suback
```js
{
cmd: 'suback',
messageId: 42,
properties: { // MQTT 5.0 properties
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
granted: [0, 1, 2, 128]
}
```
All the granted qos __must__ be < 256, as they are encoded as UInt8.
All properties are mandatory.
### Unsubscribe
```js
{
cmd: 'unsubscribe',
messageId: 42,
properties: { // MQTT 5.0 properties
userProperties: {
'test': 'test'
}
}
unsubscriptions: [
'test',
'a/topic'
]
}
```
All properties are mandatory.
### Unsuback
```js
{
cmd: 'unsuback',
messageId: 42,
properties: { // MQTT 5.0 properties
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
All properties are mandatory.
### Publish
```js
{
cmd: 'publish',
messageId: 42,
qos: 2,
dup: false,
topic: 'test',
payload: Buffer.from('test'),
retain: false,
properties: { // optional properties MQTT 5.0
payloadFormatIndicator: true,
messageExpiryInterval: 4321,
topicAlias: 100,
responseTopic: 'topic',
correlationData: Buffer.from([1, 2, 3, 4]),
userProperties: {
'test': 'test'
},
subscriptionIdentifier: 120, // can be an Array in message from broker, if message included in few another subscriptions
contentType: 'test'
}
}
```
Only the `topic` property is mandatory.
Both `topic` and `payload` can be `Buffer` objects instead of strings.
`messageId` is mandatory for `qos > 0`.
### Puback
```js
{
cmd: 'puback',
messageId: 42,
reasonCode: 16, // only for MQTT 5.0
properties: { // MQTT 5.0 properties
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
The only mandatory property is `messageId`, as `generate` will throw if
missing.
### Pubrec
```js
{
cmd: 'pubrec',
messageId: 42,
reasonCode: 16, // only for MQTT 5.0
properties: { // properties MQTT 5.0
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
The only mandatory property is `messageId`, as `generate` will throw if
missing.
### Pubrel
```js
{
cmd: 'pubrel',
messageId: 42,
reasonCode: 16, // only for MQTT 5.0
properties: { // properties MQTT 5.0
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
The only mandatory property is `messageId`, as `generate` will throw if
missing.
### Pubcomp
```js
{
cmd: 'pubcomp',
messageId: 42,
reasonCode: 16, // only for MQTT 5.0
properties: { // properties MQTT 5.0
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
The only mandatory property is `messageId`, as `generate` will throw if
missing.
### Pingreq
```js
{
cmd: 'pingreq'
}
```
### Pingresp
```js
{
cmd: 'pingresp'
}
```
### Disconnect
```js
{
cmd: 'disconnect',
reasonCode: 0, // MQTT 5.0 code
properties: { // properties MQTT 5.0
sessionExpiryInterval: 145,
reasonString: 'test',
userProperties: {
'test': 'test'
},
serverReference: 'test'
}
}
```
### Auth
```js
{
cmd: 'auth',
reasonCode: 0, // MQTT 5.0 code
properties: { // properties MQTT 5.0
authenticationMethod: 'test',
authenticationData: Buffer.from([0, 1, 2, 3]),
reasonString: 'test',
userProperties: {
'test': 'test'
}
}
}
```
<a name="contributing"></a>
Contributing
------------
mqtt-packet is an **OPEN Open Source Project**. This means that:
> Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
See the [CONTRIBUTING.md](https://github.com/mqttjs/mqtt-packet/blob/master/CONTRIBUTING.md) file for more details.
### Contributors
mqtt-packet is only possible due to the excellent work of the following contributors:
<table><tbody>
<tr><th align="left">Matteo Collina</th><td><a href="https://github.com/mcollina">GitHub/mcollina</a></td><td><a href="http://twitter.com/matteocollina">Twitter/@matteocollina</a></td></tr>
<tr><th align="left">Adam Rudd</th><td><a href="https://github.com/adamvr">GitHub/adamvr</a></td><td><a href="http://twitter.com/adam_vr">Twitter/@adam_vr</a></td></tr>
<tr><th align="left">Peter Sorowka</th><td><a href="https://github.com/psorowka">GitHub/psorowka</a></td><td><a href="http://twitter.com/psorowka">Twitter/@psorowka</a></td></tr>
<tr><th align="left">Siarhei Buntsevich</th><td><a href="https://github.com/scarry1992">GitHub/scarry1992</a></td></tr>
</tbody></table>
License
-------
MIT

26
node_modules/mqtt-packet/benchmarks/generate.js generated vendored Executable file
View File

@@ -0,0 +1,26 @@
const mqtt = require('../')
const max = 100000
let i
const buf = Buffer.from('test')
// initialize it
mqtt.generate({
cmd: 'publish',
topic: 'test',
payload: buf
})
const start = Date.now()
for (i = 0; i < max; i++) {
mqtt.generate({
cmd: 'publish',
topic: 'test',
payload: buf
})
}
const time = Date.now() - start
console.log('Total time', time)
console.log('Total packets', max)
console.log('Packet/s', max / time * 1000)

50
node_modules/mqtt-packet/benchmarks/generateNet.js generated vendored Executable file
View File

@@ -0,0 +1,50 @@
const mqtt = require('../')
const max = 1000000
let i = 0
const start = Date.now()
let time
const buf = Buffer.allocUnsafe(10)
const net = require('net')
const server = net.createServer(handle)
let dest
buf.fill('test')
function handle (sock) {
sock.resume()
}
server.listen(0, () => {
dest = net.connect(server.address())
dest.on('connect', tickWait)
dest.on('drain', tickWait)
dest.on('finish', () => {
time = Date.now() - start
console.log('Total time', time)
console.log('Total packets', max)
console.log('Packet/s', max / time * 1000)
server.close()
})
})
function tickWait () {
// console.log('tickWait', i)
let res = true
// var toSend = new Buffer(5 + buf.length)
for (; i < max && res; i++) {
res = dest.write(mqtt.generate({
cmd: 'publish',
topic: 'test',
payload: buf
}))
// buf.copy(toSend, 5)
// res = dest.write(toSend, 'buffer')
// console.log(res)
}
if (i >= max) {
dest.end()
}
}

19
node_modules/mqtt-packet/benchmarks/parse.js generated vendored Executable file
View File

@@ -0,0 +1,19 @@
const mqtt = require('../')
const parser = mqtt.parser()
const max = 10000000
let i
const start = Date.now() / 1000
for (i = 0; i < max; i++) {
parser.parse(Buffer.from([
48, 10, // Header (publish)
0, 4, // Topic length
116, 101, 115, 116, // Topic (test)
116, 101, 115, 116 // Payload (test)
]))
}
const time = Date.now() / 1000 - start
console.log('Total packets', max)
console.log('Total time', Math.round(time * 100) / 100)
console.log('Packet/s', max / time)

48
node_modules/mqtt-packet/benchmarks/writeToStream.js generated vendored Executable file
View File

@@ -0,0 +1,48 @@
const mqtt = require('../')
const max = 1000000
let i = 0
const start = Date.now()
let time
const buf = Buffer.allocUnsafe(10)
const net = require('net')
const server = net.createServer(handle)
let dest
function handle (sock) {
sock.resume()
}
buf.fill('test')
server.listen(0, () => {
dest = net.connect(server.address())
dest.on('connect', tickWait)
dest.on('drain', tickWait)
dest.on('finish', () => {
time = Date.now() - start
console.log('Total time', time)
console.log('Total packets', max)
console.log('Packet/s', max / time * 1000)
server.close()
})
})
function tickWait () {
let res = true
// var toSend = new Buffer(5)
for (; i < max && res; i++) {
res = mqtt.writeToStream({
cmd: 'publish',
topic: 'test',
payload: buf
}, dest)
// dest.write(toSend, 'buffer')
// res = dest.write(buf, 'buffer')
}
if (i >= max) {
dest.end()
}
}

291
node_modules/mqtt-packet/constants.js generated vendored Executable file
View File

@@ -0,0 +1,291 @@
/* Protocol - protocol constants */
const protocol = module.exports
const { Buffer } = require('buffer')
/* Command code => mnemonic */
protocol.types = {
0: 'reserved',
1: 'connect',
2: 'connack',
3: 'publish',
4: 'puback',
5: 'pubrec',
6: 'pubrel',
7: 'pubcomp',
8: 'subscribe',
9: 'suback',
10: 'unsubscribe',
11: 'unsuback',
12: 'pingreq',
13: 'pingresp',
14: 'disconnect',
15: 'auth'
}
protocol.requiredHeaderFlags = {
1: 0, // 'connect'
2: 0, // 'connack'
4: 0, // 'puback'
5: 0, // 'pubrec'
6: 2, // 'pubrel'
7: 0, // 'pubcomp'
8: 2, // 'subscribe'
9: 0, // 'suback'
10: 2, // 'unsubscribe'
11: 0, // 'unsuback'
12: 0, // 'pingreq'
13: 0, // 'pingresp'
14: 0, // 'disconnect'
15: 0 // 'auth'
}
protocol.requiredHeaderFlagsErrors = {}
for (const k in protocol.requiredHeaderFlags) {
const v = protocol.requiredHeaderFlags[k]
protocol.requiredHeaderFlagsErrors[k] = 'Invalid header flag bits, must be 0x' + v.toString(16) + ' for ' + protocol.types[k] + ' packet'
}
/* Mnemonic => Command code */
protocol.codes = {}
for (const k in protocol.types) {
const v = protocol.types[k]
protocol.codes[v] = k
}
/* Header */
protocol.CMD_SHIFT = 4
protocol.CMD_MASK = 0xF0
protocol.DUP_MASK = 0x08
protocol.QOS_MASK = 0x03
protocol.QOS_SHIFT = 1
protocol.RETAIN_MASK = 0x01
/* Length */
protocol.VARBYTEINT_MASK = 0x7F
protocol.VARBYTEINT_FIN_MASK = 0x80
protocol.VARBYTEINT_MAX = 268435455
/* Connack */
protocol.SESSIONPRESENT_MASK = 0x01
protocol.SESSIONPRESENT_HEADER = Buffer.from([protocol.SESSIONPRESENT_MASK])
protocol.CONNACK_HEADER = Buffer.from([protocol.codes.connack << protocol.CMD_SHIFT])
/* Connect */
protocol.USERNAME_MASK = 0x80
protocol.PASSWORD_MASK = 0x40
protocol.WILL_RETAIN_MASK = 0x20
protocol.WILL_QOS_MASK = 0x18
protocol.WILL_QOS_SHIFT = 3
protocol.WILL_FLAG_MASK = 0x04
protocol.CLEAN_SESSION_MASK = 0x02
protocol.CONNECT_HEADER = Buffer.from([protocol.codes.connect << protocol.CMD_SHIFT])
/* Properties */
protocol.properties = {
sessionExpiryInterval: 17,
willDelayInterval: 24,
receiveMaximum: 33,
maximumPacketSize: 39,
topicAliasMaximum: 34,
requestResponseInformation: 25,
requestProblemInformation: 23,
userProperties: 38,
authenticationMethod: 21,
authenticationData: 22,
payloadFormatIndicator: 1,
messageExpiryInterval: 2,
contentType: 3,
responseTopic: 8,
correlationData: 9,
maximumQoS: 36,
retainAvailable: 37,
assignedClientIdentifier: 18,
reasonString: 31,
wildcardSubscriptionAvailable: 40,
subscriptionIdentifiersAvailable: 41,
sharedSubscriptionAvailable: 42,
serverKeepAlive: 19,
responseInformation: 26,
serverReference: 28,
topicAlias: 35,
subscriptionIdentifier: 11
}
protocol.propertiesCodes = {}
for (const prop in protocol.properties) {
const id = protocol.properties[prop]
protocol.propertiesCodes[id] = prop
}
protocol.propertiesTypes = {
sessionExpiryInterval: 'int32',
willDelayInterval: 'int32',
receiveMaximum: 'int16',
maximumPacketSize: 'int32',
topicAliasMaximum: 'int16',
requestResponseInformation: 'byte',
requestProblemInformation: 'byte',
userProperties: 'pair',
authenticationMethod: 'string',
authenticationData: 'binary',
payloadFormatIndicator: 'byte',
messageExpiryInterval: 'int32',
contentType: 'string',
responseTopic: 'string',
correlationData: 'binary',
maximumQoS: 'int8',
retainAvailable: 'byte',
assignedClientIdentifier: 'string',
reasonString: 'string',
wildcardSubscriptionAvailable: 'byte',
subscriptionIdentifiersAvailable: 'byte',
sharedSubscriptionAvailable: 'byte',
serverKeepAlive: 'int16',
responseInformation: 'string',
serverReference: 'string',
topicAlias: 'int16',
subscriptionIdentifier: 'var'
}
function genHeader (type) {
return [0, 1, 2].map(qos => {
return [0, 1].map(dup => {
return [0, 1].map(retain => {
const buf = Buffer.alloc(1)
buf.writeUInt8(
protocol.codes[type] << protocol.CMD_SHIFT |
(dup ? protocol.DUP_MASK : 0) |
qos << protocol.QOS_SHIFT | retain, 0, true)
return buf
})
})
})
}
/* Publish */
protocol.PUBLISH_HEADER = genHeader('publish')
/* Subscribe */
protocol.SUBSCRIBE_HEADER = genHeader('subscribe')
protocol.SUBSCRIBE_OPTIONS_QOS_MASK = 0x03
protocol.SUBSCRIBE_OPTIONS_NL_MASK = 0x01
protocol.SUBSCRIBE_OPTIONS_NL_SHIFT = 2
protocol.SUBSCRIBE_OPTIONS_RAP_MASK = 0x01
protocol.SUBSCRIBE_OPTIONS_RAP_SHIFT = 3
protocol.SUBSCRIBE_OPTIONS_RH_MASK = 0x03
protocol.SUBSCRIBE_OPTIONS_RH_SHIFT = 4
protocol.SUBSCRIBE_OPTIONS_RH = [0x00, 0x10, 0x20]
protocol.SUBSCRIBE_OPTIONS_NL = 0x04
protocol.SUBSCRIBE_OPTIONS_RAP = 0x08
protocol.SUBSCRIBE_OPTIONS_QOS = [0x00, 0x01, 0x02]
/* Unsubscribe */
protocol.UNSUBSCRIBE_HEADER = genHeader('unsubscribe')
/* Confirmations */
protocol.ACKS = {
unsuback: genHeader('unsuback'),
puback: genHeader('puback'),
pubcomp: genHeader('pubcomp'),
pubrel: genHeader('pubrel'),
pubrec: genHeader('pubrec')
}
protocol.SUBACK_HEADER = Buffer.from([protocol.codes.suback << protocol.CMD_SHIFT])
/* Protocol versions */
protocol.VERSION3 = Buffer.from([3])
protocol.VERSION4 = Buffer.from([4])
protocol.VERSION5 = Buffer.from([5])
protocol.VERSION131 = Buffer.from([131])
protocol.VERSION132 = Buffer.from([132])
/* QoS */
protocol.QOS = [0, 1, 2].map(qos => {
return Buffer.from([qos])
})
/* Empty packets */
protocol.EMPTY = {
pingreq: Buffer.from([protocol.codes.pingreq << 4, 0]),
pingresp: Buffer.from([protocol.codes.pingresp << 4, 0]),
disconnect: Buffer.from([protocol.codes.disconnect << 4, 0])
}
protocol.MQTT5_PUBACK_PUBREC_CODES = {
0x00: 'Success',
0x10: 'No matching subscribers',
0x80: 'Unspecified error',
0x83: 'Implementation specific error',
0x87: 'Not authorized',
0x90: 'Topic Name invalid',
0x91: 'Packet identifier in use',
0x97: 'Quota exceeded',
0x99: 'Payload format invalid'
}
protocol.MQTT5_PUBREL_PUBCOMP_CODES = {
0x00: 'Success',
0x92: 'Packet Identifier not found'
}
protocol.MQTT5_SUBACK_CODES = {
0x00: 'Granted QoS 0',
0x01: 'Granted QoS 1',
0x02: 'Granted QoS 2',
0x80: 'Unspecified error',
0x83: 'Implementation specific error',
0x87: 'Not authorized',
0x8F: 'Topic Filter invalid',
0x91: 'Packet Identifier in use',
0x97: 'Quota exceeded',
0x9E: 'Shared Subscriptions not supported',
0xA1: 'Subscription Identifiers not supported',
0xA2: 'Wildcard Subscriptions not supported'
}
protocol.MQTT5_UNSUBACK_CODES = {
0x00: 'Success',
0x11: 'No subscription existed',
0x80: 'Unspecified error',
0x83: 'Implementation specific error',
0x87: 'Not authorized',
0x8F: 'Topic Filter invalid',
0x91: 'Packet Identifier in use'
}
protocol.MQTT5_DISCONNECT_CODES = {
0x00: 'Normal disconnection',
0x04: 'Disconnect with Will Message',
0x80: 'Unspecified error',
0x81: 'Malformed Packet',
0x82: 'Protocol Error',
0x83: 'Implementation specific error',
0x87: 'Not authorized',
0x89: 'Server busy',
0x8B: 'Server shutting down',
0x8D: 'Keep Alive timeout',
0x8E: 'Session taken over',
0x8F: 'Topic Filter invalid',
0x90: 'Topic Name invalid',
0x93: 'Receive Maximum exceeded',
0x94: 'Topic Alias invalid',
0x95: 'Packet too large',
0x96: 'Message rate too high',
0x97: 'Quota exceeded',
0x98: 'Administrative action',
0x99: 'Payload format invalid',
0x9A: 'Retain not supported',
0x9B: 'QoS not supported',
0x9C: 'Use another server',
0x9D: 'Server moved',
0x9E: 'Shared Subscriptions not supported',
0x9F: 'Connection rate exceeded',
0xA0: 'Maximum connect time',
0xA1: 'Subscription Identifiers not supported',
0xA2: 'Wildcard Subscriptions not supported'
}
protocol.MQTT5_AUTH_CODES = {
0x00: 'Success',
0x18: 'Continue authentication',
0x19: 'Re-authenticate'
}

57
node_modules/mqtt-packet/generate.js generated vendored Executable file
View File

@@ -0,0 +1,57 @@
const writeToStream = require('./writeToStream')
const { EventEmitter } = require('events')
const { Buffer } = require('buffer')
function generate (packet, opts) {
const stream = new Accumulator()
writeToStream(packet, stream, opts)
return stream.concat()
}
class Accumulator extends EventEmitter {
constructor () {
super()
this._array = new Array(20)
this._i = 0
}
write (chunk) {
this._array[this._i++] = chunk
return true
}
concat () {
let length = 0
const lengths = new Array(this._array.length)
const list = this._array
let pos = 0
let i
for (i = 0; i < list.length && list[i] !== undefined; i++) {
if (typeof list[i] !== 'string') lengths[i] = list[i].length
else lengths[i] = Buffer.byteLength(list[i])
length += lengths[i]
}
const result = Buffer.allocUnsafe(length)
for (i = 0; i < list.length && list[i] !== undefined; i++) {
if (typeof list[i] !== 'string') {
list[i].copy(result, pos)
pos += lengths[i]
} else {
result.write(list[i], pos)
pos += lengths[i]
}
}
return result
}
destroy (err) {
if (err) this.emit('error', err)
}
}
module.exports = generate

3
node_modules/mqtt-packet/mqtt.js generated vendored Executable file
View File

@@ -0,0 +1,3 @@
exports.parser = require('./parser').parser
exports.generate = require('./generate')
exports.writeToStream = require('./writeToStream')

59
node_modules/mqtt-packet/numbers.js generated vendored Executable file
View File

@@ -0,0 +1,59 @@
const { Buffer } = require('buffer')
const max = 65536
const cache = {}
// in node 6 Buffer.subarray returns a Uint8Array instead of a Buffer
// later versions return a Buffer
// alternative is Buffer.slice but that creates a new buffer
// creating new buffers takes time
// SubOk is only false on node < 8
const SubOk = Buffer.isBuffer(Buffer.from([1, 2]).subarray(0, 1))
function generateBuffer (i) {
const buffer = Buffer.allocUnsafe(2)
buffer.writeUInt8(i >> 8, 0)
buffer.writeUInt8(i & 0x00FF, 0 + 1)
return buffer
}
function generateCache () {
for (let i = 0; i < max; i++) {
cache[i] = generateBuffer(i)
}
}
function genBufVariableByteInt (num) {
const maxLength = 4 // max 4 bytes
let digit = 0
let pos = 0
const buffer = Buffer.allocUnsafe(maxLength)
do {
digit = num % 128 | 0
num = num / 128 | 0
if (num > 0) digit = digit | 0x80
buffer.writeUInt8(digit, pos++)
} while (num > 0 && pos < maxLength)
if (num > 0) {
pos = 0
}
return SubOk ? buffer.subarray(0, pos) : buffer.slice(0, pos)
}
function generate4ByteBuffer (num) {
const buffer = Buffer.allocUnsafe(4)
buffer.writeUInt32BE(num, 0)
return buffer
}
module.exports = {
cache,
generateCache,
generateNumber: generateBuffer,
genBufVariableByteInt,
generate4ByteBuffer
}

48
node_modules/mqtt-packet/package.json generated vendored Executable file
View File

@@ -0,0 +1,48 @@
{
"name": "mqtt-packet",
"version": "9.0.2",
"description": "Parse and generate MQTT packets like a breeze",
"main": "mqtt.js",
"types": "types/index.d.ts",
"contributors": [
"Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
"Adam Rudd <damvrr@gmail.com>",
"Peter Sorowka (https://github.com/psorowka)",
"Wouter Klijn <contact@wuhkuh.com> (https://github.com/wuhkuh)",
"Siarhei Buntsevich (https://github.com/scarry1992)"
],
"scripts": {
"test": "tape test.js | tap-spec && standard",
"ci": "tape test.js && node testRandom && standard"
},
"pre-commit": "test",
"repository": {
"type": "git",
"url": "https://github.com/mqttjs/mqtt-packet.git"
},
"keywords": [
"MQTT",
"packet",
"parse",
"publish",
"subscribe",
"pubsub"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/mqttjs/mqtt-packet/issues"
},
"homepage": "https://github.com/mqttjs/mqtt-packet",
"devDependencies": {
"pre-commit": "^1.2.2",
"readable-stream": "^4.4.2",
"standard": "^17.1.0",
"tap-spec": "^5.0.0",
"tape": "^5.7.2"
},
"dependencies": {
"bl": "^6.0.8",
"debug": "^4.3.4",
"process-nextick-args": "^2.0.1"
}
}

13
node_modules/mqtt-packet/packet.js generated vendored Executable file
View File

@@ -0,0 +1,13 @@
class Packet {
constructor () {
this.cmd = null
this.retain = false
this.qos = 0
this.dup = false
this.length = -1
this.topic = null
this.payload = null
}
}
module.exports = Packet

809
node_modules/mqtt-packet/parser.js generated vendored Executable file
View File

@@ -0,0 +1,809 @@
const bl = require('bl')
const { EventEmitter } = require('events')
const Packet = require('./packet')
const constants = require('./constants')
const debug = require('debug')('mqtt-packet:parser')
class Parser extends EventEmitter {
constructor () {
super()
this.parser = this.constructor.parser
}
static parser (opt) {
if (!(this instanceof Parser)) return (new Parser()).parser(opt)
this.settings = opt || {}
this._states = [
'_parseHeader',
'_parseLength',
'_parsePayload',
'_newPacket'
]
this._resetState()
return this
}
_resetState () {
debug('_resetState: resetting packet, error, _list, and _stateCounter')
this.packet = new Packet()
this.error = null
this._list = bl()
this._stateCounter = 0
}
parse (buf) {
if (this.error) this._resetState()
this._list.append(buf)
debug('parse: current state: %s', this._states[this._stateCounter])
while ((this.packet.length !== -1 || this._list.length > 0) &&
this[this._states[this._stateCounter]]() &&
!this.error) {
this._stateCounter++
debug('parse: state complete. _stateCounter is now: %d', this._stateCounter)
debug('parse: packet.length: %d, buffer list length: %d', this.packet.length, this._list.length)
if (this._stateCounter >= this._states.length) this._stateCounter = 0
}
debug('parse: exited while loop. packet: %d, buffer list length: %d', this.packet.length, this._list.length)
return this._list.length
}
_parseHeader () {
// There is at least one byte in the buffer
const zero = this._list.readUInt8(0)
const cmdIndex = zero >> constants.CMD_SHIFT
this.packet.cmd = constants.types[cmdIndex]
const headerFlags = zero & 0xf
const requiredHeaderFlags = constants.requiredHeaderFlags[cmdIndex]
if (requiredHeaderFlags != null && headerFlags !== requiredHeaderFlags) {
// Where a flag bit is marked as “Reserved” in Table 2.2 - Flag Bits, it is reserved for future use and MUST be set to the value listed in that table [MQTT-2.2.2-1]. If invalid flags are received, the receiver MUST close the Network Connection [MQTT-2.2.2-2]
return this._emitError(new Error(constants.requiredHeaderFlagsErrors[cmdIndex]))
}
this.packet.retain = (zero & constants.RETAIN_MASK) !== 0
this.packet.qos = (zero >> constants.QOS_SHIFT) & constants.QOS_MASK
if (this.packet.qos > 2) {
return this._emitError(new Error('Packet must not have both QoS bits set to 1'))
}
this.packet.dup = (zero & constants.DUP_MASK) !== 0
debug('_parseHeader: packet: %o', this.packet)
this._list.consume(1)
return true
}
_parseLength () {
// There is at least one byte in the list
const result = this._parseVarByteNum(true)
if (result) {
this.packet.length = result.value
this._list.consume(result.bytes)
}
debug('_parseLength %d', result.value)
return !!result
}
_parsePayload () {
debug('_parsePayload: payload %O', this._list)
let result = false
// Do we have a payload? Do we have enough data to complete the payload?
// PINGs have no payload
if (this.packet.length === 0 || this._list.length >= this.packet.length) {
this._pos = 0
switch (this.packet.cmd) {
case 'connect':
this._parseConnect()
break
case 'connack':
this._parseConnack()
break
case 'publish':
this._parsePublish()
break
case 'puback':
case 'pubrec':
case 'pubrel':
case 'pubcomp':
this._parseConfirmation()
break
case 'subscribe':
this._parseSubscribe()
break
case 'suback':
this._parseSuback()
break
case 'unsubscribe':
this._parseUnsubscribe()
break
case 'unsuback':
this._parseUnsuback()
break
case 'pingreq':
case 'pingresp':
// These are empty, nothing to do
break
case 'disconnect':
this._parseDisconnect()
break
case 'auth':
this._parseAuth()
break
default:
this._emitError(new Error('Not supported'))
}
result = true
}
debug('_parsePayload complete result: %s', result)
return result
}
_parseConnect () {
debug('_parseConnect')
let topic // Will topic
let payload // Will payload
let password // Password
let username // Username
const flags = {}
const packet = this.packet
// Parse protocolId
const protocolId = this._parseString()
if (protocolId === null) return this._emitError(new Error('Cannot parse protocolId'))
if (protocolId !== 'MQTT' && protocolId !== 'MQIsdp') {
return this._emitError(new Error('Invalid protocolId'))
}
packet.protocolId = protocolId
// Parse constants version number
if (this._pos >= this._list.length) return this._emitError(new Error('Packet too short'))
packet.protocolVersion = this._list.readUInt8(this._pos)
if (packet.protocolVersion >= 128) {
packet.bridgeMode = true
packet.protocolVersion = packet.protocolVersion - 128
}
if (packet.protocolVersion !== 3 && packet.protocolVersion !== 4 && packet.protocolVersion !== 5) {
return this._emitError(new Error('Invalid protocol version'))
}
this._pos++
if (this._pos >= this._list.length) {
return this._emitError(new Error('Packet too short'))
}
if (this._list.readUInt8(this._pos) & 0x1) {
// The Server MUST validate that the reserved flag in the CONNECT Control Packet is set to zero and disconnect the Client if it is not zero [MQTT-3.1.2-3]
return this._emitError(new Error('Connect flag bit 0 must be 0, but got 1'))
}
// Parse connect flags
flags.username = (this._list.readUInt8(this._pos) & constants.USERNAME_MASK)
flags.password = (this._list.readUInt8(this._pos) & constants.PASSWORD_MASK)
flags.will = (this._list.readUInt8(this._pos) & constants.WILL_FLAG_MASK)
const willRetain = !!(this._list.readUInt8(this._pos) & constants.WILL_RETAIN_MASK)
const willQos = (this._list.readUInt8(this._pos) &
constants.WILL_QOS_MASK) >> constants.WILL_QOS_SHIFT
if (flags.will) {
packet.will = {}
packet.will.retain = willRetain
packet.will.qos = willQos
} else {
if (willRetain) {
return this._emitError(new Error('Will Retain Flag must be set to zero when Will Flag is set to 0'))
}
if (willQos) {
return this._emitError(new Error('Will QoS must be set to zero when Will Flag is set to 0'))
}
}
packet.clean = (this._list.readUInt8(this._pos) & constants.CLEAN_SESSION_MASK) !== 0
this._pos++
// Parse keepalive
packet.keepalive = this._parseNum()
if (packet.keepalive === -1) return this._emitError(new Error('Packet too short'))
// parse properties
if (packet.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
// Parse clientId
const clientId = this._parseString()
if (clientId === null) return this._emitError(new Error('Packet too short'))
packet.clientId = clientId
debug('_parseConnect: packet.clientId: %s', packet.clientId)
if (flags.will) {
if (packet.protocolVersion === 5) {
const willProperties = this._parseProperties()
if (Object.getOwnPropertyNames(willProperties).length) {
packet.will.properties = willProperties
}
}
// Parse will topic
topic = this._parseString()
if (topic === null) return this._emitError(new Error('Cannot parse will topic'))
packet.will.topic = topic
debug('_parseConnect: packet.will.topic: %s', packet.will.topic)
// Parse will payload
payload = this._parseBuffer()
if (payload === null) return this._emitError(new Error('Cannot parse will payload'))
packet.will.payload = payload
debug('_parseConnect: packet.will.paylaod: %s', packet.will.payload)
}
// Parse username
if (flags.username) {
username = this._parseString()
if (username === null) return this._emitError(new Error('Cannot parse username'))
packet.username = username
debug('_parseConnect: packet.username: %s', packet.username)
}
// Parse password
if (flags.password) {
password = this._parseBuffer()
if (password === null) return this._emitError(new Error('Cannot parse password'))
packet.password = password
}
// need for right parse auth packet and self set up
this.settings = packet
debug('_parseConnect: complete')
return packet
}
_parseConnack () {
debug('_parseConnack')
const packet = this.packet
if (this._list.length < 1) return null
const flags = this._list.readUInt8(this._pos++)
if (flags > 1) {
return this._emitError(new Error('Invalid connack flags, bits 7-1 must be set to 0'))
}
packet.sessionPresent = !!(flags & constants.SESSIONPRESENT_MASK)
if (this.settings.protocolVersion === 5) {
if (this._list.length >= 2) {
packet.reasonCode = this._list.readUInt8(this._pos++)
} else {
packet.reasonCode = 0
}
} else {
if (this._list.length < 2) return null
packet.returnCode = this._list.readUInt8(this._pos++)
}
if (packet.returnCode === -1 || packet.reasonCode === -1) return this._emitError(new Error('Cannot parse return code'))
// mqtt 5 properties
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
debug('_parseConnack: complete')
}
_parsePublish () {
debug('_parsePublish')
const packet = this.packet
packet.topic = this._parseString()
if (packet.topic === null) return this._emitError(new Error('Cannot parse topic'))
// Parse messageId
if (packet.qos > 0) if (!this._parseMessageId()) { return }
// Properties mqtt 5
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
packet.payload = this._list.slice(this._pos, packet.length)
debug('_parsePublish: payload from buffer list: %o', packet.payload)
}
_parseSubscribe () {
debug('_parseSubscribe')
const packet = this.packet
let topic
let options
let qos
let rh
let rap
let nl
let subscription
packet.subscriptions = []
if (!this._parseMessageId()) { return }
// Properties mqtt 5
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
if (packet.length <= 0) { return this._emitError(new Error('Malformed subscribe, no payload specified')) }
while (this._pos < packet.length) {
// Parse topic
topic = this._parseString()
if (topic === null) return this._emitError(new Error('Cannot parse topic'))
if (this._pos >= packet.length) return this._emitError(new Error('Malformed Subscribe Payload'))
options = this._parseByte()
if (this.settings.protocolVersion === 5) {
if (options & 0xc0) {
return this._emitError(new Error('Invalid subscribe topic flag bits, bits 7-6 must be 0'))
}
} else {
if (options & 0xfc) {
return this._emitError(new Error('Invalid subscribe topic flag bits, bits 7-2 must be 0'))
}
}
qos = options & constants.SUBSCRIBE_OPTIONS_QOS_MASK
if (qos > 2) {
return this._emitError(new Error('Invalid subscribe QoS, must be <= 2'))
}
nl = ((options >> constants.SUBSCRIBE_OPTIONS_NL_SHIFT) & constants.SUBSCRIBE_OPTIONS_NL_MASK) !== 0
rap = ((options >> constants.SUBSCRIBE_OPTIONS_RAP_SHIFT) & constants.SUBSCRIBE_OPTIONS_RAP_MASK) !== 0
rh = (options >> constants.SUBSCRIBE_OPTIONS_RH_SHIFT) & constants.SUBSCRIBE_OPTIONS_RH_MASK
if (rh > 2) {
return this._emitError(new Error('Invalid retain handling, must be <= 2'))
}
subscription = { topic, qos }
// mqtt 5 options
if (this.settings.protocolVersion === 5) {
subscription.nl = nl
subscription.rap = rap
subscription.rh = rh
} else if (this.settings.bridgeMode) {
subscription.rh = 0
subscription.rap = true
subscription.nl = true
}
// Push pair to subscriptions
debug('_parseSubscribe: push subscription `%s` to subscription', subscription)
packet.subscriptions.push(subscription)
}
}
_parseSuback () {
debug('_parseSuback')
const packet = this.packet
this.packet.granted = []
if (!this._parseMessageId()) { return }
// Properties mqtt 5
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
if (packet.length <= 0) { return this._emitError(new Error('Malformed suback, no payload specified')) }
// Parse granted QoSes
while (this._pos < this.packet.length) {
const code = this._list.readUInt8(this._pos++)
if (this.settings.protocolVersion === 5) {
if (!constants.MQTT5_SUBACK_CODES[code]) {
return this._emitError(new Error('Invalid suback code'))
}
} else {
if (code > 2 && code !== 0x80) {
return this._emitError(new Error('Invalid suback QoS, must be 0, 1, 2 or 128'))
}
}
this.packet.granted.push(code)
}
}
_parseUnsubscribe () {
debug('_parseUnsubscribe')
const packet = this.packet
packet.unsubscriptions = []
// Parse messageId
if (!this._parseMessageId()) { return }
// Properties mqtt 5
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
if (packet.length <= 0) { return this._emitError(new Error('Malformed unsubscribe, no payload specified')) }
while (this._pos < packet.length) {
// Parse topic
const topic = this._parseString()
if (topic === null) return this._emitError(new Error('Cannot parse topic'))
// Push topic to unsubscriptions
debug('_parseUnsubscribe: push topic `%s` to unsubscriptions', topic)
packet.unsubscriptions.push(topic)
}
}
_parseUnsuback () {
debug('_parseUnsuback')
const packet = this.packet
if (!this._parseMessageId()) return this._emitError(new Error('Cannot parse messageId'))
if ((this.settings.protocolVersion === 3 ||
this.settings.protocolVersion === 4) && packet.length !== 2) {
return this._emitError(new Error('Malformed unsuback, payload length must be 2'))
}
if (packet.length <= 0) { return this._emitError(new Error('Malformed unsuback, no payload specified')) }
// Properties mqtt 5
if (this.settings.protocolVersion === 5) {
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
// Parse granted QoSes
packet.granted = []
while (this._pos < this.packet.length) {
const code = this._list.readUInt8(this._pos++)
if (!constants.MQTT5_UNSUBACK_CODES[code]) {
return this._emitError(new Error('Invalid unsuback code'))
}
this.packet.granted.push(code)
}
}
}
// parse packets like puback, pubrec, pubrel, pubcomp
_parseConfirmation () {
debug('_parseConfirmation: packet.cmd: `%s`', this.packet.cmd)
const packet = this.packet
this._parseMessageId()
if (this.settings.protocolVersion === 5) {
if (packet.length > 2) {
// response code
packet.reasonCode = this._parseByte()
switch (this.packet.cmd) {
case 'puback':
case 'pubrec':
if (!constants.MQTT5_PUBACK_PUBREC_CODES[packet.reasonCode]) {
return this._emitError(new Error('Invalid ' + this.packet.cmd + ' reason code'))
}
break
case 'pubrel':
case 'pubcomp':
if (!constants.MQTT5_PUBREL_PUBCOMP_CODES[packet.reasonCode]) {
return this._emitError(new Error('Invalid ' + this.packet.cmd + ' reason code'))
}
break
}
debug('_parseConfirmation: packet.reasonCode `%d`', packet.reasonCode)
} else {
packet.reasonCode = 0
}
if (packet.length > 3) {
// properies mqtt 5
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
}
return true
}
// parse disconnect packet
_parseDisconnect () {
const packet = this.packet
debug('_parseDisconnect')
if (this.settings.protocolVersion === 5) {
// response code
if (this._list.length > 0) {
packet.reasonCode = this._parseByte()
if (!constants.MQTT5_DISCONNECT_CODES[packet.reasonCode]) {
this._emitError(new Error('Invalid disconnect reason code'))
}
} else {
packet.reasonCode = 0
}
// properies mqtt 5
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
}
debug('_parseDisconnect result: true')
return true
}
// parse auth packet
_parseAuth () {
debug('_parseAuth')
const packet = this.packet
if (this.settings.protocolVersion !== 5) {
return this._emitError(new Error('Not supported auth packet for this version MQTT'))
}
// response code
packet.reasonCode = this._parseByte()
if (!constants.MQTT5_AUTH_CODES[packet.reasonCode]) {
return this._emitError(new Error('Invalid auth reason code'))
}
// properies mqtt 5
const properties = this._parseProperties()
if (Object.getOwnPropertyNames(properties).length) {
packet.properties = properties
}
debug('_parseAuth: result: true')
return true
}
_parseMessageId () {
const packet = this.packet
packet.messageId = this._parseNum()
if (packet.messageId === null) {
this._emitError(new Error('Cannot parse messageId'))
return false
}
debug('_parseMessageId: packet.messageId %d', packet.messageId)
return true
}
_parseString (maybeBuffer) {
const length = this._parseNum()
const end = length + this._pos
if (length === -1 || end > this._list.length || end > this.packet.length) return null
const result = this._list.toString('utf8', this._pos, end)
this._pos += length
debug('_parseString: result: %s', result)
return result
}
_parseStringPair () {
debug('_parseStringPair')
return {
name: this._parseString(),
value: this._parseString()
}
}
_parseBuffer () {
const length = this._parseNum()
const end = length + this._pos
if (length === -1 || end > this._list.length || end > this.packet.length) return null
const result = this._list.slice(this._pos, end)
this._pos += length
debug('_parseBuffer: result: %o', result)
return result
}
_parseNum () {
if (this._list.length - this._pos < 2) return -1
const result = this._list.readUInt16BE(this._pos)
this._pos += 2
debug('_parseNum: result: %s', result)
return result
}
_parse4ByteNum () {
if (this._list.length - this._pos < 4) return -1
const result = this._list.readUInt32BE(this._pos)
this._pos += 4
debug('_parse4ByteNum: result: %s', result)
return result
}
_parseVarByteNum (fullInfoFlag) {
debug('_parseVarByteNum')
const maxBytes = 4
let bytes = 0
let mul = 1
let value = 0
let result = false
let current
const padding = this._pos ? this._pos : 0
while (bytes < maxBytes && (padding + bytes) < this._list.length) {
current = this._list.readUInt8(padding + bytes++)
value += mul * (current & constants.VARBYTEINT_MASK)
mul *= 0x80
if ((current & constants.VARBYTEINT_FIN_MASK) === 0) {
result = true
break
}
if (this._list.length <= bytes) {
break
}
}
if (!result && bytes === maxBytes && this._list.length >= bytes) {
this._emitError(new Error('Invalid variable byte integer'))
}
if (padding) {
this._pos += bytes
}
if (result) {
if (fullInfoFlag) {
result = { bytes, value }
} else {
result = value
}
} else {
result = false
}
debug('_parseVarByteNum: result: %o', result)
return result
}
_parseByte () {
let result
if (this._pos < this._list.length) {
result = this._list.readUInt8(this._pos)
this._pos++
}
debug('_parseByte: result: %o', result)
return result
}
_parseByType (type) {
debug('_parseByType: type: %s', type)
switch (type) {
case 'byte': {
return this._parseByte() !== 0
}
case 'int8': {
return this._parseByte()
}
case 'int16': {
return this._parseNum()
}
case 'int32': {
return this._parse4ByteNum()
}
case 'var': {
return this._parseVarByteNum()
}
case 'string': {
return this._parseString()
}
case 'pair': {
return this._parseStringPair()
}
case 'binary': {
return this._parseBuffer()
}
}
}
_parseProperties () {
debug('_parseProperties')
const length = this._parseVarByteNum()
const start = this._pos
const end = start + length
const result = {}
while (this._pos < end) {
const type = this._parseByte()
if (!type) {
this._emitError(new Error('Cannot parse property code type'))
return false
}
const name = constants.propertiesCodes[type]
if (!name) {
this._emitError(new Error('Unknown property'))
return false
}
// user properties process
if (name === 'userProperties') {
if (!result[name]) {
result[name] = Object.create(null)
}
const currentUserProperty = this._parseByType(constants.propertiesTypes[name])
if (result[name][currentUserProperty.name]) {
if (Array.isArray(result[name][currentUserProperty.name])) {
result[name][currentUserProperty.name].push(currentUserProperty.value)
} else {
const currentValue = result[name][currentUserProperty.name]
result[name][currentUserProperty.name] = [currentValue]
result[name][currentUserProperty.name].push(currentUserProperty.value)
}
} else {
result[name][currentUserProperty.name] = currentUserProperty.value
}
continue
}
if (result[name]) {
if (Array.isArray(result[name])) {
result[name].push(this._parseByType(constants.propertiesTypes[name]))
} else {
result[name] = [result[name]]
result[name].push(this._parseByType(constants.propertiesTypes[name]))
}
} else {
result[name] = this._parseByType(constants.propertiesTypes[name])
}
}
return result
}
_newPacket () {
debug('_newPacket')
if (this.packet) {
this._list.consume(this.packet.length)
debug('_newPacket: parser emit packet: packet.cmd: %s, packet.payload: %s, packet.length: %d', this.packet.cmd, this.packet.payload, this.packet.length)
this.emit('packet', this.packet)
}
debug('_newPacket: new packet')
this.packet = new Packet()
this._pos = 0
return true
}
_emitError (err) {
debug('_emitError', err)
this.error = err
this.emit('error', err)
}
}
module.exports = Parser

3234
node_modules/mqtt-packet/test.js generated vendored Executable file

File diff suppressed because it is too large Load Diff

86
node_modules/mqtt-packet/testRandom.js generated vendored Executable file
View File

@@ -0,0 +1,86 @@
const mqtt = require('./')
const crypto = require('crypto')
const max = 1E5
const start = Date.now() / 1000
let errors = 0
let packets = 0
let randomPacket
const firstBytes = [
16 * 1, // CONNECT
16 * 2, // CONNACK
16 * 3, // PUBLISH, QoS: 0, No Retain, No Dup
16 * 3 + 1, // PUBLISH, QoS: 0, Retain, No Dup
16 * 3 + 8, // PUBLISH, QoS: 0, No Retain, Dup
16 * 3 + 1 + 8, // PUBLISH, QoS: 0, Retain, Dup
16 * 3 + 2, // PUBLISH, QoS: 1, No Retain, No Dup
16 * 3 + 2 + 1, // PUBLISH, QoS: 1, Retain, No Dup
16 * 3 + 2 + 8, // PUBLISH, QoS: 1, No Retain, Dup
16 * 3 + 2 + 1 + 8, // PUBLISH, QoS: 1, Retain, Dup
16 * 3 + 4, // PUBLISH, QoS: 2, No Retain, No Dup
16 * 3 + 4 + 1, // PUBLISH, QoS: 2, Retain, No Dup
16 * 3 + 4 + 8, // PUBLISH, QoS: 2, No Retain, Dup
16 * 3 + 4 + 1 + 8, // PUBLISH, QoS: 2, Retain, Dup
16 * 4, // PUBACK
16 * 5, // PUBREC
16 * 6, // PUBREL
16 * 7, // PUBCOMP
16 * 8, // SUBSCRIBE
16 * 9, // SUBACK
16 * 10, // UNSUBSCRIBE
16 * 11, // UNSUBACK
16 * 12, // PINGREQ
16 * 13, // PINGRESP
16 * 14, // DISCONNECT
16 * 15 // RESERVED
]
function doParse () {
const parser = mqtt.parser()
parser.on('error', onError)
parser.on('packet', onPacket)
randomPacket = crypto.randomBytes(Math.floor(Math.random() * 512))
// Increase probability to have a valid first byte in order to at least
// enter the parser
if (Math.random() > 0.2 && randomPacket.length > 0) randomPacket.writeUInt8(firstBytes[Math.floor(Math.random() * firstBytes.length)], 0)
parser.parse(randomPacket)
}
try {
console.log('Starting benchmark')
for (let i = 0; i < max; i++) {
doParse()
}
} catch (e) {
console.log('Exception occurred at packet')
console.log(randomPacket)
console.log(e.message)
console.log(e.stack)
}
function onError () {
errors++
}
function onPacket () {
packets++
}
const delta = Math.abs(max - packets - errors)
const time = Date.now() / 1000 - start
console.log('Benchmark complete')
console.log('==========================')
console.log('Sent packets:', max)
console.log('Total time:', Math.round(time * 100) / 100, 'seconds', '\r\n')
console.log('Valid packets:', packets)
console.log('Erroneous packets:', errors)
if ((max - packets - errors) < 0) console.log('Excess packets:', delta, '\r\n')
else console.log('Missing packets:', delta, '\r\n')
console.log('Total packets:', packets + errors)
console.log('Total errors:', errors + delta)
console.log('Error rate:', `${((errors + delta) / max * 100).toFixed(2)}%`)
console.log('==========================')

257
node_modules/mqtt-packet/types/index.d.ts generated vendored Executable file
View File

@@ -0,0 +1,257 @@
import EventEmitter = NodeJS.EventEmitter
import WritableStream = NodeJS.WritableStream
export declare type QoS = 0 | 1 | 2
export declare type PacketCmd = 'auth' |
'connack' |
'connect' |
'disconnect' |
'pingreq' |
'pingresp' |
'puback' |
'pubcomp' |
'publish' |
'pubrel' |
'pubrec' |
'suback' |
'subscribe' |
'unsuback' |
'unsubscribe'
export declare type UserProperties = {[index: string]: string | string[]}
export interface IPacket {
cmd: PacketCmd
messageId?: number
length?: number
}
export interface IAuthPacket extends IPacket {
cmd: 'auth'
reasonCode: number,
properties?: {
authenticationMethod?: string,
authenticationData?: Buffer,
reasonString?: string,
userProperties?: UserProperties,
}
}
export interface IConnectPacket extends IPacket {
cmd: 'connect'
clientId: string
protocolVersion?: 4 | 5 | 3
protocolId?: 'MQTT' | 'MQIsdp'
clean?: boolean
keepalive?: number
username?: string
password?: Buffer
will?: {
topic: string
payload: Buffer | string
qos?: QoS
retain?: boolean
properties?: {
willDelayInterval?: number,
payloadFormatIndicator?: boolean,
messageExpiryInterval?: number,
contentType?: string,
responseTopic?: string,
correlationData?: Buffer,
userProperties?: UserProperties
}
}
properties?: {
sessionExpiryInterval?: number,
receiveMaximum?: number,
maximumPacketSize?: number,
topicAliasMaximum?: number,
requestResponseInformation?: boolean,
requestProblemInformation?: boolean,
userProperties?: UserProperties,
authenticationMethod?: string,
authenticationData?: Buffer
}
}
export interface IPublishPacket extends IPacket {
cmd: 'publish'
qos: QoS
dup: boolean
retain: boolean
topic: string
payload: string | Buffer
properties?: {
payloadFormatIndicator?: boolean,
messageExpiryInterval?: number,
topicAlias?: number,
responseTopic?: string,
correlationData?: Buffer,
userProperties?: UserProperties,
subscriptionIdentifier?: number | number[],
contentType?: string
}
}
export interface IConnackPacket extends IPacket {
cmd: 'connack'
returnCode?: number,
reasonCode?: number,
sessionPresent: boolean
properties?: {
sessionExpiryInterval?: number,
receiveMaximum?: number,
maximumQoS?: number,
retainAvailable?: boolean,
maximumPacketSize?: number,
assignedClientIdentifier?: string,
topicAliasMaximum?: number,
reasonString?: string,
userProperties?: UserProperties,
wildcardSubscriptionAvailable?: boolean,
subscriptionIdentifiersAvailable?: boolean,
sharedSubscriptionAvailable?: boolean,
serverKeepAlive?: number,
responseInformation?: string,
serverReference?: string,
authenticationMethod?: string,
authenticationData?: Buffer
}
}
export interface ISubscription {
topic: string
qos: QoS,
nl?: boolean,
rap?: boolean,
rh?: number
}
export interface ISubscribePacket extends IPacket {
cmd: 'subscribe'
subscriptions: ISubscription[],
properties?: {
reasonString?: string,
subscriptionIdentifier?: number,
userProperties?: UserProperties
}
}
export interface ISubackPacket extends IPacket {
cmd: 'suback',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
},
granted: number[] | Object[]
}
export interface IUnsubscribePacket extends IPacket {
cmd: 'unsubscribe',
properties?: {
reasonString?: string,
userProperties?: UserProperties
},
unsubscriptions: string[]
}
export interface IUnsubackPacket extends IPacket {
cmd: 'unsuback',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
},
granted: number[]
}
export interface IPubackPacket extends IPacket {
cmd: 'puback',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
}
}
export interface IPubcompPacket extends IPacket {
cmd: 'pubcomp',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
}
}
export interface IPubrelPacket extends IPacket {
cmd: 'pubrel',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
}
}
export interface IPubrecPacket extends IPacket {
cmd: 'pubrec',
reasonCode?: number,
properties?: {
reasonString?: string,
userProperties?: UserProperties
}
}
export interface IPingreqPacket extends IPacket {
cmd: 'pingreq'
}
export interface IPingrespPacket extends IPacket {
cmd: 'pingresp'
}
export interface IDisconnectPacket extends IPacket {
cmd: 'disconnect',
reasonCode?: number,
properties?: {
sessionExpiryInterval?: number,
reasonString?: string,
userProperties?: UserProperties,
serverReference?: string
}
}
export declare type Packet = IConnectPacket |
IPublishPacket |
IConnackPacket |
ISubscribePacket |
ISubackPacket |
IUnsubscribePacket |
IUnsubackPacket |
IPubackPacket |
IPubcompPacket |
IPubrelPacket |
IPingreqPacket |
IPingrespPacket |
IDisconnectPacket |
IPubrecPacket |
IAuthPacket
export interface Parser extends EventEmitter {
on(event: 'packet', callback: (packet: Packet) => void): this
on(event: 'error', callback: (error: any) => void): this
parse(buffer: Buffer, opts?: Object): number
}
export declare function parser(opts?: Object): Parser
export declare function generate(packet: Packet, opts?: Object): Buffer
export declare function writeToStream(object: Packet, stream: WritableStream, opts?: Object): boolean
export declare namespace writeToStream {
let cacheNumbers: boolean
}

1129
node_modules/mqtt-packet/writeToStream.js generated vendored Executable file

File diff suppressed because it is too large Load Diff