mqtt and socket added
This commit is contained in:
27
WebUI/node_modules/mqtt/CONTRIBUTING.md
generated
vendored
Normal file
27
WebUI/node_modules/mqtt/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# MQTT.js 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-main 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.
|
||||
|
||||
-----------------------------------------
|
||||
15
WebUI/node_modules/mqtt/LICENSE.md
generated
vendored
Normal file
15
WebUI/node_modules/mqtt/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright (c) 2015-2016 MQTT.js contributors
|
||||
---------------------------------------
|
||||
|
||||
*MQTT.js contributors listed at <https://github.com/mqttjs/MQTT.js#contributors>*
|
||||
|
||||
Copyright 2011-2014 by Adam Rudd
|
||||
|
||||
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.
|
||||
847
WebUI/node_modules/mqtt/README.md
generated
vendored
Normal file
847
WebUI/node_modules/mqtt/README.md
generated
vendored
Normal file
@@ -0,0 +1,847 @@
|
||||

|
||||
=======
|
||||
|
||||
 [](https://codecov.io/gh/mqttjs/MQTT.js)
|
||||
|
||||
MQTT.js is a client library for the [MQTT](http://mqtt.org/) protocol, written
|
||||
in JavaScript for node.js and the browser.
|
||||
|
||||
| :boom: MQTT.js vNext |
|
||||
|:---------------------------|
|
||||
| Want to contribute to the next generation of **MQTT.js**? Join the discussion [here](https://github.com/mqttjs/MQTT.js/discussions/1324). |
|
||||
|
||||
## Table of Contents
|
||||
* [__MQTT.js vNext__](#vnext)
|
||||
* [Upgrade notes](#notes)
|
||||
* [Installation](#install)
|
||||
* [Example](#example)
|
||||
* [Import Styles](#example)
|
||||
* [Command Line Tools](#cli)
|
||||
* [API](#api)
|
||||
* [Browser](#browser)
|
||||
* [About QoS](#qos)
|
||||
* [TypeScript](#typescript)
|
||||
* [Weapp and Ali support](#weapp-alipay)
|
||||
* [Contributing](#contributing)
|
||||
* [License](#license)
|
||||
|
||||
MQTT.js is an OPEN Open Source Project, see the [Contributing](#contributing) section to find out what this means.
|
||||
|
||||
[](https://github.com/feross/standard)
|
||||
|
||||
<a name="vnext"></a>
|
||||
## Discussion on the next major version of MQTT.js
|
||||
There are discussions happening on the future of MQTT.js and the next major version (vNext). We invite the community to provide their thoughts and feedback in [this GitHub discussion](https://github.com/mqttjs/MQTT.js/discussions/1324)
|
||||
|
||||
<a name="notes"></a>
|
||||
## Important notes for existing users
|
||||
|
||||
__v4.0.0__ (Released 04/2020) removes support for all end of life node versions, and now supports node v12 and v14. It also adds improvements to
|
||||
debug logging, along with some feature additions.
|
||||
|
||||
As a __breaking change__, by default a error handler is built into the MQTT.js client, so if any
|
||||
errors are emitted and the user has not created an event handler on the client for errors, the client will
|
||||
not break as a result of unhandled errors. Additionally, typical TLS errors like `ECONNREFUSED`, `ECONNRESET` have been
|
||||
added to a list of TLS errors that will be emitted from the MQTT.js client, and so can be handled as connection errors.
|
||||
|
||||
__v3.0.0__ adds support for MQTT 5, support for node v10.x, and many fixes to improve reliability.
|
||||
|
||||
__Note:__ MQTT v5 support is experimental as it has not been implemented by brokers yet.
|
||||
|
||||
__v2.0.0__ removes support for node v0.8, v0.10 and v0.12, and it is 3x faster in sending
|
||||
packets. It also removes all the deprecated functionality in v1.0.0,
|
||||
mainly `mqtt.createConnection` and `mqtt.Server`. From v2.0.0,
|
||||
subscriptions are restored upon reconnection if `clean: true`.
|
||||
v1.x.x is now in *LTS*, and it will keep being supported as long as
|
||||
there are v0.8, v0.10 and v0.12 users.
|
||||
|
||||
As a __breaking change__, the `encoding` option in the old client is
|
||||
removed, and now everything is UTF-8 with the exception of the
|
||||
`password` in the CONNECT message and `payload` in the PUBLISH message,
|
||||
which are `Buffer`.
|
||||
|
||||
Another __breaking change__ is that MQTT.js now defaults to MQTT v3.1.1,
|
||||
so to support old brokers, please read the [client options doc](#client).
|
||||
|
||||
__v1.0.0__ improves the overall architecture of the project, which is now
|
||||
split into three components: MQTT.js keeps the Client,
|
||||
[mqtt-connection](http://npm.im/mqtt-connection) includes the barebone
|
||||
Connection code for server-side usage, and [mqtt-packet](http://npm.im/mqtt-packet)
|
||||
includes the protocol parser and generator. The new Client improves
|
||||
performance by a 30% factor, embeds Websocket support
|
||||
([MOWS](http://npm.im/mows) is now deprecated), and it has a better
|
||||
support for QoS 1 and 2. The previous API is still supported but
|
||||
deprecated, as such, it is not documented in this README.
|
||||
|
||||
<a name="install"></a>
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install mqtt --save
|
||||
```
|
||||
|
||||
<a name="example"></a>
|
||||
## Example
|
||||
|
||||
For the sake of simplicity, let's put the subscriber and the publisher in the same file:
|
||||
|
||||
```js
|
||||
const mqtt = require('mqtt')
|
||||
const client = mqtt.connect('mqtt://test.mosquitto.org')
|
||||
|
||||
client.on('connect', function () {
|
||||
client.subscribe('presence', function (err) {
|
||||
if (!err) {
|
||||
client.publish('presence', 'Hello mqtt')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
client.on('message', function (topic, message) {
|
||||
// message is Buffer
|
||||
console.log(message.toString())
|
||||
client.end()
|
||||
})
|
||||
```
|
||||
|
||||
output:
|
||||
```
|
||||
Hello mqtt
|
||||
```
|
||||
|
||||
If you want to run your own MQTT broker, you can use
|
||||
[Mosquitto](http://mosquitto.org) or
|
||||
[Aedes-cli](https://github.com/moscajs/aedes-cli), and launch it.
|
||||
|
||||
You can also use a test instance: test.mosquitto.org.
|
||||
|
||||
If you do not want to install a separate broker, you can try using the
|
||||
[Aedes](https://github.com/moscajs/aedes).
|
||||
|
||||
to use MQTT.js in the browser see the [browserify](#browserify) section
|
||||
|
||||
<a name="import_styles"></a>
|
||||
## Import styles
|
||||
### CommonJS (Require)
|
||||
```js
|
||||
const mqtt = require('mqtt') // require mqtt
|
||||
const client = mqtt.connect('est.mosquitto.org') // create a client
|
||||
```
|
||||
### ES6 Modules (Import)
|
||||
#### Aliased wildcard import
|
||||
```js
|
||||
import * as mqtt from "mqtt" // import everything inside the mqtt module and give it the namespace "mqtt"
|
||||
let client = mqtt.connect('mqtt://test.mosquitto.org') // create a client
|
||||
```
|
||||
#### Importing individual components
|
||||
```js
|
||||
import { connect } from "mqtt" // import connect from mqtt
|
||||
let client = connect('mqtt://test.mosquitto.org') // create a client
|
||||
```
|
||||
|
||||
<a name="promises"></a>
|
||||
## Promise support
|
||||
|
||||
If you want to use the new [async-await](https://blog.risingstack.com/async-await-node-js-7-nightly/) functionality in JavaScript, or just prefer using Promises instead of callbacks, [async-mqtt](https://github.com/mqttjs/async-mqtt) is a wrapper over MQTT.js which uses promises instead of callbacks when possible.
|
||||
|
||||
<a name="cli"></a>
|
||||
## Command Line Tools
|
||||
|
||||
MQTT.js bundles a command to interact with a broker.
|
||||
In order to have it available on your path, you should install MQTT.js
|
||||
globally:
|
||||
|
||||
```sh
|
||||
npm install mqtt -g
|
||||
```
|
||||
|
||||
Then, on one terminal
|
||||
|
||||
```
|
||||
mqtt sub -t 'hello' -h 'test.mosquitto.org' -v
|
||||
```
|
||||
|
||||
On another
|
||||
|
||||
```
|
||||
mqtt pub -t 'hello' -h 'test.mosquitto.org' -m 'from MQTT.js'
|
||||
```
|
||||
|
||||
See `mqtt help <command>` for the command help.
|
||||
|
||||
<a name="debug"></a>
|
||||
## Debug Logs
|
||||
|
||||
MQTT.js uses the [debug](https://www.npmjs.com/package/debug#cmd) package for debugging purposes. To enable debug logs, add the following environment variable on runtime :
|
||||
```ps
|
||||
# (example using PowerShell, the VS Code default)
|
||||
$env:DEBUG='mqttjs*'
|
||||
|
||||
```
|
||||
|
||||
<a name="reconnecting"></a>
|
||||
## About Reconnection
|
||||
|
||||
An important part of any websocket connection is what to do when a connection
|
||||
drops off and the client needs to reconnect. MQTT has built-in reconnection
|
||||
support that can be configured to behave in ways that suit the application.
|
||||
|
||||
#### Refresh Authentication Options / Signed Urls with `transformWsUrl` (Websocket Only)
|
||||
|
||||
When an mqtt connection drops and needs to reconnect, it's common to require
|
||||
that any authentication associated with the connection is kept current with
|
||||
the underlying auth mechanism. For instance some applications may pass an auth
|
||||
token with connection options on the initial connection, while other cloud
|
||||
services may require a url be signed with each connection.
|
||||
|
||||
By the time the reconnect happens in the application lifecycle, the original
|
||||
auth data may have expired.
|
||||
|
||||
To address this we can use a hook called `transformWsUrl` to manipulate
|
||||
either of the connection url or the client options at the time of a reconnect.
|
||||
|
||||
Example (update clientId & username on each reconnect):
|
||||
```
|
||||
const transformWsUrl = (url, options, client) => {
|
||||
client.options.username = `token=${this.get_current_auth_token()}`;
|
||||
client.options.clientId = `${this.get_updated_clientId()}`;
|
||||
|
||||
return `${this.get_signed_cloud_url(url)`;
|
||||
}
|
||||
|
||||
const connection = await mqtt.connectAsync(<wss url>, {
|
||||
...,
|
||||
transformWsUrl: transformUrl,
|
||||
});
|
||||
|
||||
```
|
||||
Now every time a new WebSocket connection is opened (hopefully not too often),
|
||||
we will get a fresh signed url or fresh auth token data.
|
||||
|
||||
Note: Currently this hook does _not_ support promises, meaning that in order to
|
||||
use the latest auth token, you must have some outside mechanism running that
|
||||
handles application-level authentication refreshing so that the websocket
|
||||
connection can simply grab the latest valid token or signed url.
|
||||
|
||||
|
||||
#### Enabling Reconnection with `reconnectPeriod` option
|
||||
|
||||
To ensure that the mqtt client automatically tries to reconnect when the
|
||||
connection is dropped, you must set the client option `reconnectPeriod` to a
|
||||
value greater than 0. A value of 0 will disable reconnection and then terminate
|
||||
the final connection when it drops.
|
||||
|
||||
The default value is 1000 ms which means it will try to reconnect 1 second
|
||||
after losing the connection.
|
||||
|
||||
<a name="topicalias"></a>
|
||||
## About Topic Alias Management
|
||||
|
||||
### Enabling automatic Topic Alias using
|
||||
If the client sets the option `autoUseTopicAlias:true` then MQTT.js uses existing topic alias automatically.
|
||||
|
||||
example scenario:
|
||||
```
|
||||
1. PUBLISH topic:'t1', ta:1 (register)
|
||||
2. PUBLISH topic:'t1' -> topic:'', ta:1 (auto use existing map entry)
|
||||
3. PUBLISH topic:'t2', ta:1 (register overwrite)
|
||||
4. PUBLISH topic:'t2' -> topic:'', ta:1 (auto use existing map entry based on the receent map)
|
||||
5. PUBLISH topic:'t1' (t1 is no longer mapped to ta:1)
|
||||
```
|
||||
|
||||
User doesn't need to manage which topic is mapped to which topic alias.
|
||||
If the user want to register topic alias, then publish topic with topic alias.
|
||||
If the user want to use topic alias, then publish topic without topic alias. If there is a mapped topic alias then added it as a property and update the topic to empty string.
|
||||
|
||||
### Enabling automatic Topic Alias assign
|
||||
|
||||
If the client sets the option `autoAssignTopicAlias:true` then MQTT.js uses existing topic alias automatically.
|
||||
If no topic alias exists, then assign a new vacant topic alias automatically. If topic alias is fully used, then LRU(Least Recently Used) topic-alias entry is overwritten.
|
||||
|
||||
example scenario:
|
||||
```
|
||||
The broker returns CONNACK (TopicAliasMaximum:3)
|
||||
1. PUBLISH topic:'t1' -> 't1', ta:1 (auto assign t1:1 and register)
|
||||
2. PUBLISH topic:'t1' -> '' , ta:1 (auto use existing map entry)
|
||||
3. PUBLISH topic:'t2' -> 't2', ta:2 (auto assign t1:2 and register. 2 was vacant)
|
||||
4. PUBLISH topic:'t3' -> 't3', ta:3 (auto assign t1:3 and register. 3 was vacant)
|
||||
5. PUBLISH topic:'t4' -> 't4', ta:1 (LRU entry is overwritten)
|
||||
```
|
||||
|
||||
Also user can manually register topic-alias pair using PUBLISH topic:'some', ta:X. It works well with automatic topic alias assign.
|
||||
|
||||
<a name="api"></a>
|
||||
## API
|
||||
|
||||
* <a href="#connect"><code>mqtt.<b>connect()</b></code></a>
|
||||
* <a href="#client"><code>mqtt.<b>Client()</b></code></a>
|
||||
* <a href="#publish"><code>mqtt.Client#<b>publish()</b></code></a>
|
||||
* <a href="#subscribe"><code>mqtt.Client#<b>subscribe()</b></code></a>
|
||||
* <a href="#unsubscribe"><code>mqtt.Client#<b>unsubscribe()</b></code></a>
|
||||
* <a href="#end"><code>mqtt.Client#<b>end()</b></code></a>
|
||||
* <a href="#removeOutgoingMessage"><code>mqtt.Client#<b>removeOutgoingMessage()</b></code></a>
|
||||
* <a href="#reconnect"><code>mqtt.Client#<b>reconnect()</b></code></a>
|
||||
* <a href="#handleMessage"><code>mqtt.Client#<b>handleMessage()</b></code></a>
|
||||
* <a href="#connected"><code>mqtt.Client#<b>connected</b></code></a>
|
||||
* <a href="#reconnecting"><code>mqtt.Client#<b>reconnecting</b></code></a>
|
||||
* <a href="#getLastMessageId"><code>mqtt.Client#<b>getLastMessageId()</b></code></a>
|
||||
* <a href="#store"><code>mqtt.<b>Store()</b></code></a>
|
||||
* <a href="#put"><code>mqtt.Store#<b>put()</b></code></a>
|
||||
* <a href="#del"><code>mqtt.Store#<b>del()</b></code></a>
|
||||
* <a href="#createStream"><code>mqtt.Store#<b>createStream()</b></code></a>
|
||||
* <a href="#close"><code>mqtt.Store#<b>close()</b></code></a>
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="connect"></a>
|
||||
### mqtt.connect([url], options)
|
||||
|
||||
Connects to the broker specified by the given url and options and
|
||||
returns a [Client](#client).
|
||||
|
||||
The URL can be on the following protocols: 'mqtt', 'mqtts', 'tcp',
|
||||
'tls', 'ws', 'wss', 'wxs', 'alis'. The URL can also be an object as returned by
|
||||
[`URL.parse()`](http://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost),
|
||||
in that case the two objects are merged, i.e. you can pass a single
|
||||
object with both the URL and the connect options.
|
||||
|
||||
You can also specify a `servers` options with content: `[{ host:
|
||||
'localhost', port: 1883 }, ... ]`, in that case that array is iterated
|
||||
at every connect.
|
||||
|
||||
For all MQTT-related options, see the [Client](#client)
|
||||
constructor.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="client"></a>
|
||||
### mqtt.Client(streamBuilder, options)
|
||||
|
||||
The `Client` class wraps a client connection to an
|
||||
MQTT broker over an arbitrary transport method (TCP, TLS,
|
||||
WebSocket, ecc).
|
||||
|
||||
`Client` automatically handles the following:
|
||||
|
||||
* Regular server pings
|
||||
* QoS flow
|
||||
* Automatic reconnections
|
||||
* Start publishing before being connected
|
||||
|
||||
The arguments are:
|
||||
|
||||
* `streamBuilder` is a function that returns a subclass of the `Stream` class that supports
|
||||
the `connect` event. Typically a `net.Socket`.
|
||||
* `options` is the client connection options (see: the [connect packet](https://github.com/mcollina/mqtt-packet#connect)). Defaults:
|
||||
* `wsOptions`: is the WebSocket connection options. Default is `{}`.
|
||||
It's specific for WebSockets. For possible options have a look at: https://github.com/websockets/ws/blob/master/doc/ws.md.
|
||||
* `keepalive`: `60` seconds, set to `0` to disable
|
||||
* `reschedulePings`: reschedule ping messages after sending packets (default `true`)
|
||||
* `clientId`: `'mqttjs_' + Math.random().toString(16).substr(2, 8)`
|
||||
* `protocolId`: `'MQTT'`
|
||||
* `protocolVersion`: `4`
|
||||
* `clean`: `true`, set to false to receive QoS 1 and 2 messages while
|
||||
offline
|
||||
* `reconnectPeriod`: `1000` milliseconds, interval between two
|
||||
reconnections. Disable auto reconnect by setting to `0`.
|
||||
* `connectTimeout`: `30 * 1000` milliseconds, time to wait before a
|
||||
CONNACK is received
|
||||
* `username`: the username required by your broker, if any
|
||||
* `password`: the password required by your broker, if any
|
||||
* `incomingStore`: a [Store](#store) for the incoming packets
|
||||
* `outgoingStore`: a [Store](#store) for the outgoing packets
|
||||
* `queueQoSZero`: if connection is broken, queue outgoing QoS zero messages (default `true`)
|
||||
* `customHandleAcks`: MQTT 5 feature of custom handling puback and pubrec packets. Its callback:
|
||||
```js
|
||||
customHandleAcks: function(topic, message, packet, done) {/*some logic wit colling done(error, reasonCode)*/}
|
||||
```
|
||||
* `autoUseTopicAlias`: enabling automatic Topic Alias using functionality
|
||||
* `autoAssignTopicAlias`: enabling automatic Topic Alias assign functionality
|
||||
* `properties`: properties MQTT 5.0.
|
||||
`object` that supports the following properties:
|
||||
* `sessionExpiryInterval`: representing the Session Expiry Interval in seconds `number`,
|
||||
* `receiveMaximum`: representing the Receive Maximum value `number`,
|
||||
* `maximumPacketSize`: representing the Maximum Packet Size the Client is willing to accept `number`,
|
||||
* `topicAliasMaximum`: representing the Topic Alias Maximum value indicates the highest value that the Client will accept as a Topic Alias sent by the Server `number`,
|
||||
* `requestResponseInformation`: The Client uses this value to request the Server to return Response Information in the CONNACK `boolean`,
|
||||
* `requestProblemInformation`: The Client uses this value to indicate whether the Reason String or User Properties are sent in the case of failures `boolean`,
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`,
|
||||
* `authenticationMethod`: the name of the authentication method used for extended authentication `string`,
|
||||
* `authenticationData`: Binary Data containing authentication data `binary`
|
||||
* `authPacket`: settings for auth packet `object`
|
||||
* `will`: a message that will sent by the broker automatically when
|
||||
the client disconnect badly. The format is:
|
||||
* `topic`: the topic to publish
|
||||
* `payload`: the message to publish
|
||||
* `qos`: the QoS
|
||||
* `retain`: the retain flag
|
||||
* `properties`: properties of will by MQTT 5.0:
|
||||
* `willDelayInterval`: representing the Will Delay Interval in seconds `number`,
|
||||
* `payloadFormatIndicator`: Will Message is UTF-8 Encoded Character Data or not `boolean`,
|
||||
* `messageExpiryInterval`: value is the lifetime of the Will Message in seconds and is sent as the Publication Expiry Interval when the Server publishes the Will Message `number`,
|
||||
* `contentType`: describing the content of the Will Message `string`,
|
||||
* `responseTopic`: String which is used as the Topic Name for a response message `string`,
|
||||
* `correlationData`: The Correlation Data is used by the sender of the Request Message to identify which request the Response Message is for when it is received `binary`,
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`
|
||||
* `transformWsUrl` : optional `(url, options, client) => url` function
|
||||
For ws/wss protocols only. Can be used to implement signing
|
||||
urls which upon reconnect can have become expired.
|
||||
* `resubscribe` : if connection is broken and reconnects,
|
||||
subscribed topics are automatically subscribed again (default `true`)
|
||||
* `messageIdProvider`: custom messageId provider. when `new UniqueMessageIdProvider()` is set, then non conflict messageId is provided.
|
||||
|
||||
In case mqtts (mqtt over tls) is required, the `options` object is
|
||||
passed through to
|
||||
[`tls.connect()`](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
|
||||
If you are using a **self-signed certificate**, pass the `rejectUnauthorized: false` option.
|
||||
Beware that you are exposing yourself to man in the middle attacks, so it is a configuration
|
||||
that is not recommended for production environments.
|
||||
|
||||
If you are connecting to a broker that supports only MQTT 3.1 (not
|
||||
3.1.1 compliant), you should pass these additional options:
|
||||
|
||||
```js
|
||||
{
|
||||
protocolId: 'MQIsdp',
|
||||
protocolVersion: 3
|
||||
}
|
||||
```
|
||||
|
||||
This is confirmed on RabbitMQ 3.2.4, and on Mosquitto < 1.3. Mosquitto
|
||||
version 1.3 and 1.4 works fine without those.
|
||||
|
||||
#### Event `'connect'`
|
||||
|
||||
`function (connack) {}`
|
||||
|
||||
Emitted on successful (re)connection (i.e. connack rc=0).
|
||||
* `connack` received connack packet. When `clean` connection option is `false` and server has a previous session
|
||||
for `clientId` connection option, then `connack.sessionPresent` flag is `true`. When that is the case,
|
||||
you may rely on stored session and prefer not to send subscribe commands for the client.
|
||||
|
||||
#### Event `'reconnect'`
|
||||
|
||||
`function () {}`
|
||||
|
||||
Emitted when a reconnect starts.
|
||||
|
||||
#### Event `'close'`
|
||||
|
||||
`function () {}`
|
||||
|
||||
Emitted after a disconnection.
|
||||
|
||||
#### Event `'disconnect'`
|
||||
|
||||
`function (packet) {}`
|
||||
|
||||
Emitted after receiving disconnect packet from broker. MQTT 5.0 feature.
|
||||
|
||||
#### Event `'offline'`
|
||||
|
||||
`function () {}`
|
||||
|
||||
Emitted when the client goes offline.
|
||||
|
||||
#### Event `'error'`
|
||||
|
||||
`function (error) {}`
|
||||
|
||||
Emitted when the client cannot connect (i.e. connack rc != 0) or when a
|
||||
parsing error occurs.
|
||||
|
||||
The following TLS errors will be emitted as an `error` event:
|
||||
|
||||
* `ECONNREFUSED`
|
||||
* `ECONNRESET`
|
||||
* `EADDRINUSE`
|
||||
* `ENOTFOUND`
|
||||
|
||||
#### Event `'end'`
|
||||
|
||||
`function () {}`
|
||||
|
||||
Emitted when <a href="#end"><code>mqtt.Client#<b>end()</b></code></a> is called.
|
||||
If a callback was passed to `mqtt.Client#end()`, this event is emitted once the
|
||||
callback returns.
|
||||
|
||||
#### Event `'message'`
|
||||
|
||||
`function (topic, message, packet) {}`
|
||||
|
||||
Emitted when the client receives a publish packet
|
||||
* `topic` topic of the received packet
|
||||
* `message` payload of the received packet
|
||||
* `packet` received packet, as defined in
|
||||
[mqtt-packet](https://github.com/mcollina/mqtt-packet#publish)
|
||||
|
||||
#### Event `'packetsend'`
|
||||
|
||||
`function (packet) {}`
|
||||
|
||||
Emitted when the client sends any packet. This includes .published() packets
|
||||
as well as packets used by MQTT for managing subscriptions and connections
|
||||
* `packet` received packet, as defined in
|
||||
[mqtt-packet](https://github.com/mcollina/mqtt-packet)
|
||||
|
||||
#### Event `'packetreceive'`
|
||||
|
||||
`function (packet) {}`
|
||||
|
||||
Emitted when the client receives any packet. This includes packets from
|
||||
subscribed topics as well as packets used by MQTT for managing subscriptions
|
||||
and connections
|
||||
* `packet` received packet, as defined in
|
||||
[mqtt-packet](https://github.com/mcollina/mqtt-packet)
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="publish"></a>
|
||||
### mqtt.Client#publish(topic, message, [options], [callback])
|
||||
|
||||
Publish a message to a topic
|
||||
|
||||
* `topic` is the topic to publish to, `String`
|
||||
* `message` is the message to publish, `Buffer` or `String`
|
||||
* `options` is the options to publish with, including:
|
||||
* `qos` QoS level, `Number`, default `0`
|
||||
* `retain` retain flag, `Boolean`, default `false`
|
||||
* `dup` mark as duplicate flag, `Boolean`, default `false`
|
||||
* `properties`: MQTT 5.0 properties `object`
|
||||
* `payloadFormatIndicator`: Payload is UTF-8 Encoded Character Data or not `boolean`,
|
||||
* `messageExpiryInterval`: the lifetime of the Application Message in seconds `number`,
|
||||
* `topicAlias`: value that is used to identify the Topic instead of using the Topic Name `number`,
|
||||
* `responseTopic`: String which is used as the Topic Name for a response message `string`,
|
||||
* `correlationData`: used by the sender of the Request Message to identify which request the Response Message is for when it is received `binary`,
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`,
|
||||
* `subscriptionIdentifier`: representing the identifier of the subscription `number`,
|
||||
* `contentType`: String describing the content of the Application Message `string`
|
||||
* `cbStorePut` - `function ()`, fired when message is put into `outgoingStore` if QoS is `1` or `2`.
|
||||
* `callback` - `function (err)`, fired when the QoS handling completes,
|
||||
or at the next tick if QoS 0. An error occurs if client is disconnecting.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="subscribe"></a>
|
||||
### mqtt.Client#subscribe(topic/topic array/topic object, [options], [callback])
|
||||
|
||||
Subscribe to a topic or topics
|
||||
|
||||
* `topic` is a `String` topic to subscribe to or an `Array` of
|
||||
topics to subscribe to. It can also be an object, it has as object
|
||||
keys the topic name and as value the QoS, like `{'test1': {qos: 0}, 'test2': {qos: 1}}`.
|
||||
MQTT `topic` wildcard characters are supported (`+` - for single level and `#` - for multi level)
|
||||
* `options` is the options to subscribe with, including:
|
||||
* `qos` QoS subscription level, default 0
|
||||
* `nl` No Local MQTT 5.0 flag (If the value is true, Application Messages MUST NOT be forwarded to a connection with a ClientID equal to the ClientID of the publishing connection)
|
||||
* `rap` Retain as Published MQTT 5.0 flag (If true, Application Messages forwarded using this subscription keep the RETAIN flag they were published with. If false, Application Messages forwarded using this subscription have the RETAIN flag set to 0.)
|
||||
* `rh` Retain Handling MQTT 5.0 (This option specifies whether retained messages are sent when the subscription is established.)
|
||||
* `properties`: `object`
|
||||
* `subscriptionIdentifier`: representing the identifier of the subscription `number`,
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`
|
||||
* `callback` - `function (err, granted)`
|
||||
callback fired on suback where:
|
||||
* `err` a subscription error or an error that occurs when client is disconnecting
|
||||
* `granted` is an array of `{topic, qos}` where:
|
||||
* `topic` is a subscribed to topic
|
||||
* `qos` is the granted QoS level on it
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="unsubscribe"></a>
|
||||
### mqtt.Client#unsubscribe(topic/topic array, [options], [callback])
|
||||
|
||||
Unsubscribe from a topic or topics
|
||||
|
||||
* `topic` is a `String` topic or an array of topics to unsubscribe from
|
||||
* `options`: options of unsubscribe.
|
||||
* `properties`: `object`
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`
|
||||
* `callback` - `function (err)`, fired on unsuback. An error occurs if client is disconnecting.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="end"></a>
|
||||
### mqtt.Client#end([force], [options], [callback])
|
||||
|
||||
Close the client, accepts the following options:
|
||||
|
||||
* `force`: passing it to true will close the client right away, without
|
||||
waiting for the in-flight messages to be acked. This parameter is
|
||||
optional.
|
||||
* `options`: options of disconnect.
|
||||
* `reasonCode`: Disconnect Reason Code `number`
|
||||
* `properties`: `object`
|
||||
* `sessionExpiryInterval`: representing the Session Expiry Interval in seconds `number`,
|
||||
* `reasonString`: representing the reason for the disconnect `string`,
|
||||
* `userProperties`: The User Property is allowed to appear multiple times to represent multiple name, value pairs `object`,
|
||||
* `serverReference`: String which can be used by the Client to identify another Server to use `string`
|
||||
* `callback`: will be called when the client is closed. This parameter is
|
||||
optional.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="removeOutgoingMessage"></a>
|
||||
### mqtt.Client#removeOutgoingMessage(mId)
|
||||
|
||||
Remove a message from the outgoingStore.
|
||||
The outgoing callback will be called with Error('Message removed') if the message is removed.
|
||||
|
||||
After this function is called, the messageId is released and becomes reusable.
|
||||
|
||||
* `mId`: The messageId of the message in the outgoingStore.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="reconnect"></a>
|
||||
### mqtt.Client#reconnect()
|
||||
|
||||
Connect again using the same options as connect()
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="handleMessage"></a>
|
||||
### mqtt.Client#handleMessage(packet, callback)
|
||||
|
||||
Handle messages with backpressure support, one at a time.
|
||||
Override at will, but __always call `callback`__, or the client
|
||||
will hang.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="connected"></a>
|
||||
### mqtt.Client#connected
|
||||
|
||||
Boolean : set to `true` if the client is connected. `false` otherwise.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="getLastMessageId"></a>
|
||||
### mqtt.Client#getLastMessageId()
|
||||
|
||||
Number : get last message id. This is for sent messages only.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="reconnecting"></a>
|
||||
### mqtt.Client#reconnecting
|
||||
|
||||
Boolean : set to `true` if the client is trying to reconnect to the server. `false` otherwise.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="store"></a>
|
||||
### mqtt.Store(options)
|
||||
|
||||
In-memory implementation of the message store.
|
||||
|
||||
* `options` is the store options:
|
||||
* `clean`: `true`, clean inflight messages when close is called (default `true`)
|
||||
|
||||
Other implementations of `mqtt.Store`:
|
||||
|
||||
* [mqtt-level-store](http://npm.im/mqtt-level-store) which uses
|
||||
[Level-browserify](http://npm.im/level-browserify) to store the inflight
|
||||
data, making it usable both in Node and the Browser.
|
||||
* [mqtt-nedb-store](https://github.com/behrad/mqtt-nedb-store) which
|
||||
uses [nedb](https://www.npmjs.com/package/nedb) to store the inflight
|
||||
data.
|
||||
* [mqtt-localforage-store](http://npm.im/mqtt-localforage-store) which uses
|
||||
[localForage](http://npm.im/localforage) to store the inflight
|
||||
data, making it usable in the Browser without browserify.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="put"></a>
|
||||
### mqtt.Store#put(packet, callback)
|
||||
|
||||
Adds a packet to the store, a packet is
|
||||
anything that has a `messageId` property.
|
||||
The callback is called when the packet has been stored.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="createStream"></a>
|
||||
### mqtt.Store#createStream()
|
||||
|
||||
Creates a stream with all the packets in the store.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="del"></a>
|
||||
### mqtt.Store#del(packet, cb)
|
||||
|
||||
Removes a packet from the store, a packet is
|
||||
anything that has a `messageId` property.
|
||||
The callback is called when the packet has been removed.
|
||||
|
||||
-------------------------------------------------------
|
||||
<a name="close"></a>
|
||||
### mqtt.Store#close(cb)
|
||||
|
||||
Closes the Store.
|
||||
|
||||
<a name="browser"></a>
|
||||
## Browser
|
||||
|
||||
<a name="cdn"></a>
|
||||
### Via CDN
|
||||
|
||||
The MQTT.js bundle is available through http://unpkg.com, specifically
|
||||
at https://unpkg.com/mqtt/dist/mqtt.min.js.
|
||||
See http://unpkg.com for the full documentation on version ranges.
|
||||
|
||||
<a name="browserify"></a>
|
||||
### Browserify
|
||||
|
||||
In order to use MQTT.js as a browserify module you can either require it in your browserify bundles or build it as a stand alone module. The exported module is AMD/CommonJs compatible and it will add an object in the global space.
|
||||
|
||||
```bash
|
||||
mkdir tmpdir
|
||||
cd tmpdir
|
||||
npm install mqtt
|
||||
npm install browserify
|
||||
npm install tinyify
|
||||
cd node_modules/mqtt/
|
||||
npm install .
|
||||
npx browserify mqtt.js -s mqtt >browserMqtt.js // use script tag
|
||||
# show size for compressed browser transfer
|
||||
gzip <browserMqtt.js | wc -c
|
||||
```
|
||||
|
||||
**Be sure to only use this bundle with `ws` or `wss` URLs in the browser. Others URL types will likey fail**
|
||||
|
||||
<a name="webpack"></a>
|
||||
### Webpack
|
||||
|
||||
Just like browserify, export MQTT.js as library. The exported module would be `const mqtt = xxx` and it will add an object in the global space. You could also export module in other [formats (AMD/CommonJS/others)](http://webpack.github.io/docs/configuration.html#output-librarytarget) by setting **output.libraryTarget** in webpack configuration.
|
||||
|
||||
```javascript
|
||||
npm install -g webpack // install webpack
|
||||
|
||||
cd node_modules/mqtt
|
||||
npm install . // install dev dependencies
|
||||
webpack mqtt.js ./browserMqtt.js --output-library mqtt
|
||||
```
|
||||
|
||||
you can then use mqtt.js in the browser with the same api than node's one.
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>test Ws mqtt.js</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="./browserMqtt.js"></script>
|
||||
<script>
|
||||
const client = mqtt.connect() // you add a ws:// url here
|
||||
client.subscribe("mqtt/demo")
|
||||
|
||||
client.on("message", function (topic, payload) {
|
||||
alert([topic, payload].join(": "))
|
||||
client.end()
|
||||
})
|
||||
|
||||
client.publish("mqtt/demo", "hello world!")
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### React
|
||||
```
|
||||
npm install -g webpack // Install webpack globally
|
||||
npm install mqtt // Install MQTT library
|
||||
cd node_modules/mqtt
|
||||
npm install . // Install dev deps at current dir
|
||||
webpack mqtt.js --output-library mqtt // Build
|
||||
|
||||
// now you can import the library with ES6 import, commonJS not tested
|
||||
```
|
||||
|
||||
|
||||
```javascript
|
||||
import React from 'react';
|
||||
import mqtt from 'mqtt';
|
||||
|
||||
export default () => {
|
||||
const [connectionStatus, setConnectionStatus] = React.useState(false);
|
||||
const [messages, setMessages] = React.useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const client = mqtt.connect(SOME_URL);
|
||||
client.on('connect', () => setConnectionStatus(true));
|
||||
client.on('message', (topic, payload, packet) => {
|
||||
setMessages(messages.concat(payload.toString()));
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{messages.map((message) => (
|
||||
<h2>{message}</h2>
|
||||
)
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Your broker should accept websocket connection (see [MQTT over Websockets](https://github.com/moscajs/aedes/blob/master/docs/Examples.md#mqtt-server-over-websocket-using-server-factory) to setup [Aedes](https://github.com/moscajs/aedes)).
|
||||
|
||||
<a name="qos"></a>
|
||||
## About QoS
|
||||
|
||||
Here is how QoS works:
|
||||
|
||||
* QoS 0 : received **at most once** : The packet is sent, and that's it. There is no validation about whether it has been received.
|
||||
* QoS 1 : received **at least once** : The packet is sent and stored as long as the client has not received a confirmation from the server. MQTT ensures that it *will* be received, but there can be duplicates.
|
||||
* QoS 2 : received **exactly once** : Same as QoS 1 but there is no duplicates.
|
||||
|
||||
About data consumption, obviously, QoS 2 > QoS 1 > QoS 0, if that's a concern to you.
|
||||
|
||||
<a name="typescript"></a>
|
||||
## Usage with TypeScript
|
||||
This repo bundles TypeScript definition files for use in TypeScript projects and to support tools that can read `.d.ts` files.
|
||||
|
||||
### Pre-requisites
|
||||
Before you can begin using these TypeScript definitions with your project, you need to make sure your project meets a few of these requirements:
|
||||
* TypeScript >= 2.1
|
||||
* Set tsconfig.json: `{"compilerOptions" : {"moduleResolution" : "node"}, ...}`
|
||||
* Includes the TypeScript definitions for node. You can use npm to install this by typing the following into a terminal window:
|
||||
`npm install --save-dev @types/node`
|
||||
|
||||
### Typescript example
|
||||
```
|
||||
import * as mqtt from "mqtt"
|
||||
let client : mqtt.MqttClient = mqtt.connect('mqtt://test.mosquitto.org')
|
||||
```
|
||||
|
||||
<a name="weapp-alipay"></a>
|
||||
## WeChat and Ali Mini Program support
|
||||
### WeChat Mini Program
|
||||
Supports [WeChat Mini Program](https://mp.weixin.qq.com/). Use the `wxs` protocol. See [the WeChat docs](https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-socket.html).
|
||||
|
||||
```js
|
||||
const mqtt = require('mqtt')
|
||||
const client = mqtt.connect('wxs://test.mosquitto.org')
|
||||
```
|
||||
|
||||
### Ali Mini Program
|
||||
Supports [Ali Mini Program](https://open.alipay.com/channel/miniIndex.htm). Use the `alis` protocol. See [the Alipay docs](https://docs.alipay.com/mini/developer/getting-started).
|
||||
<a name="example"></a>
|
||||
|
||||
```js
|
||||
const mqtt = require('mqtt')
|
||||
const client = mqtt.connect('alis://test.mosquitto.org')
|
||||
```
|
||||
|
||||
<a name="contributing"></a>
|
||||
## Contributing
|
||||
|
||||
MQTT.js 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.js/blob/master/CONTRIBUTING.md) file for more details.
|
||||
|
||||
### Contributors
|
||||
|
||||
MQTT.js is only possible due to the excellent work of the following contributors:
|
||||
|
||||
<table><tbody>
|
||||
<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">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">Maxime Agor</th><td><a href="https://github.com/4rzael">GitHub/4rzael</a></td><td><a href="http://twitter.com/4rzael">Twitter/@4rzael</a></td></tr>
|
||||
<tr><th align="left">Siarhei Buntsevich</th><td><a href="https://github.com/scarry1992">GitHub/scarry1992</a></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
|
||||
<a name="license"></a>
|
||||
## License
|
||||
|
||||
MIT
|
||||
27
WebUI/node_modules/mqtt/bin/mqtt.js
generated
vendored
Normal file
27
WebUI/node_modules/mqtt/bin/mqtt.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict'
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2015 MQTT.js contributors.
|
||||
* Copyright (c) 2011-2014 Adam Rudd.
|
||||
*
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
const path = require('path')
|
||||
const commist = require('commist')()
|
||||
const helpMe = require('help-me')({
|
||||
dir: path.join(path.dirname(require.main.filename), '/../doc'),
|
||||
ext: '.txt'
|
||||
})
|
||||
|
||||
commist.register('publish', require('./pub'))
|
||||
commist.register('subscribe', require('./sub'))
|
||||
commist.register('version', function () {
|
||||
console.log('MQTT.js version:', require('./../package.json').version)
|
||||
})
|
||||
commist.register('help', helpMe.toStdout)
|
||||
|
||||
if (commist.parse(process.argv.slice(2)) !== null) {
|
||||
console.log('No such command:', process.argv[2], '\n')
|
||||
helpMe.toStdout()
|
||||
}
|
||||
146
WebUI/node_modules/mqtt/bin/pub.js
generated
vendored
Normal file
146
WebUI/node_modules/mqtt/bin/pub.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
const mqtt = require('../')
|
||||
const pump = require('pump')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const concat = require('concat-stream')
|
||||
const Writable = require('readable-stream').Writable
|
||||
const helpMe = require('help-me')({
|
||||
dir: path.join(__dirname, '..', 'doc')
|
||||
})
|
||||
const minimist = require('minimist')
|
||||
const split2 = require('split2')
|
||||
|
||||
function send (args) {
|
||||
const client = mqtt.connect(args)
|
||||
client.on('connect', function () {
|
||||
client.publish(args.topic, args.message, args, function (err) {
|
||||
if (err) {
|
||||
console.warn(err)
|
||||
}
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
client.on('error', function (err) {
|
||||
console.warn(err)
|
||||
client.end()
|
||||
})
|
||||
}
|
||||
|
||||
function multisend (args) {
|
||||
const client = mqtt.connect(args)
|
||||
const sender = new Writable({
|
||||
objectMode: true
|
||||
})
|
||||
sender._write = function (line, enc, cb) {
|
||||
client.publish(args.topic, line.trim(), args, cb)
|
||||
}
|
||||
|
||||
client.on('connect', function () {
|
||||
pump(process.stdin, split2(), sender, function (err) {
|
||||
client.end()
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function start (args) {
|
||||
args = minimist(args, {
|
||||
string: ['hostname', 'username', 'password', 'key', 'cert', 'ca', 'message', 'clientId', 'i', 'id'],
|
||||
boolean: ['stdin', 'retain', 'help', 'insecure', 'multiline'],
|
||||
alias: {
|
||||
port: 'p',
|
||||
hostname: ['h', 'host'],
|
||||
topic: 't',
|
||||
message: 'm',
|
||||
qos: 'q',
|
||||
clientId: ['i', 'id'],
|
||||
retain: 'r',
|
||||
username: 'u',
|
||||
password: 'P',
|
||||
stdin: 's',
|
||||
multiline: 'M',
|
||||
protocol: ['C', 'l'],
|
||||
help: 'H',
|
||||
ca: 'cafile'
|
||||
},
|
||||
default: {
|
||||
host: 'localhost',
|
||||
qos: 0,
|
||||
retain: false,
|
||||
topic: '',
|
||||
message: ''
|
||||
}
|
||||
})
|
||||
|
||||
if (args.help) {
|
||||
return helpMe.toStdout('publish')
|
||||
}
|
||||
|
||||
if (args.key) {
|
||||
args.key = fs.readFileSync(args.key)
|
||||
}
|
||||
|
||||
if (args.cert) {
|
||||
args.cert = fs.readFileSync(args.cert)
|
||||
}
|
||||
|
||||
if (args.ca) {
|
||||
args.ca = fs.readFileSync(args.ca)
|
||||
}
|
||||
|
||||
if (args.key && args.cert && !args.protocol) {
|
||||
args.protocol = 'mqtts'
|
||||
}
|
||||
|
||||
if (args.port) {
|
||||
if (typeof args.port !== 'number') {
|
||||
console.warn('# Port: number expected, \'%s\' was given.', typeof args.port)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (args['will-topic']) {
|
||||
args.will = {}
|
||||
args.will.topic = args['will-topic']
|
||||
args.will.payload = args['will-message']
|
||||
args.will.qos = args['will-qos']
|
||||
args.will.retain = args['will-retain']
|
||||
}
|
||||
|
||||
if (args.insecure) {
|
||||
args.rejectUnauthorized = false
|
||||
}
|
||||
|
||||
args.topic = (args.topic || args._.shift()).toString()
|
||||
args.message = (args.message || args._.shift()).toString()
|
||||
|
||||
if (!args.topic) {
|
||||
console.error('missing topic\n')
|
||||
return helpMe.toStdout('publish')
|
||||
}
|
||||
|
||||
if (args.stdin) {
|
||||
if (args.multiline) {
|
||||
multisend(args)
|
||||
} else {
|
||||
process.stdin.pipe(concat(function (data) {
|
||||
args.message = data
|
||||
send(args)
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
send(args)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = start
|
||||
|
||||
if (require.main === module) {
|
||||
start(process.argv.slice(2))
|
||||
}
|
||||
123
WebUI/node_modules/mqtt/bin/sub.js
generated
vendored
Normal file
123
WebUI/node_modules/mqtt/bin/sub.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const mqtt = require('../')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const helpMe = require('help-me')({
|
||||
dir: path.join(__dirname, '..', 'doc')
|
||||
})
|
||||
const minimist = require('minimist')
|
||||
|
||||
function start (args) {
|
||||
args = minimist(args, {
|
||||
string: ['hostname', 'username', 'password', 'key', 'cert', 'ca', 'clientId', 'i', 'id'],
|
||||
boolean: ['stdin', 'help', 'clean', 'insecure'],
|
||||
alias: {
|
||||
port: 'p',
|
||||
hostname: ['h', 'host'],
|
||||
topic: 't',
|
||||
qos: 'q',
|
||||
clean: 'c',
|
||||
keepalive: 'k',
|
||||
clientId: ['i', 'id'],
|
||||
username: 'u',
|
||||
password: 'P',
|
||||
protocol: ['C', 'l'],
|
||||
verbose: 'v',
|
||||
help: '-H',
|
||||
ca: 'cafile'
|
||||
},
|
||||
default: {
|
||||
host: 'localhost',
|
||||
qos: 0,
|
||||
retain: false,
|
||||
clean: true,
|
||||
keepAlive: 30 // 30 sec
|
||||
}
|
||||
})
|
||||
|
||||
if (args.help) {
|
||||
return helpMe.toStdout('subscribe')
|
||||
}
|
||||
|
||||
args.topic = args.topic || args._.shift()
|
||||
|
||||
if (!args.topic) {
|
||||
console.error('missing topic\n')
|
||||
return helpMe.toStdout('subscribe')
|
||||
}
|
||||
|
||||
if (args.key) {
|
||||
args.key = fs.readFileSync(args.key)
|
||||
}
|
||||
|
||||
if (args.cert) {
|
||||
args.cert = fs.readFileSync(args.cert)
|
||||
}
|
||||
|
||||
if (args.ca) {
|
||||
args.ca = fs.readFileSync(args.ca)
|
||||
}
|
||||
|
||||
if (args.key && args.cert && !args.protocol) {
|
||||
args.protocol = 'mqtts'
|
||||
}
|
||||
|
||||
if (args.insecure) {
|
||||
args.rejectUnauthorized = false
|
||||
}
|
||||
|
||||
if (args.port) {
|
||||
if (typeof args.port !== 'number') {
|
||||
console.warn('# Port: number expected, \'%s\' was given.', typeof args.port)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (args['will-topic']) {
|
||||
args.will = {}
|
||||
args.will.topic = args['will-topic']
|
||||
args.will.payload = args['will-message']
|
||||
args.will.qos = args['will-qos']
|
||||
args.will.retain = args['will-retain']
|
||||
}
|
||||
|
||||
args.keepAlive = args['keep-alive']
|
||||
|
||||
const client = mqtt.connect(args)
|
||||
|
||||
client.on('connect', function () {
|
||||
client.subscribe(args.topic, { qos: args.qos }, function (err, result) {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
result.forEach(function (sub) {
|
||||
if (sub.qos > 2) {
|
||||
console.error('subscription negated to', sub.topic, 'with code', sub.qos)
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
client.on('message', function (topic, payload) {
|
||||
if (args.verbose) {
|
||||
console.log(topic, payload.toString())
|
||||
} else {
|
||||
console.log(payload.toString())
|
||||
}
|
||||
})
|
||||
|
||||
client.on('error', function (err) {
|
||||
console.warn(err)
|
||||
client.end()
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = start
|
||||
|
||||
if (require.main === module) {
|
||||
start(process.argv.slice(2))
|
||||
}
|
||||
18984
WebUI/node_modules/mqtt/dist/mqtt.js
generated
vendored
Normal file
18984
WebUI/node_modules/mqtt/dist/mqtt.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
WebUI/node_modules/mqtt/dist/mqtt.min.js
generated
vendored
Normal file
1
WebUI/node_modules/mqtt/dist/mqtt.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8
WebUI/node_modules/mqtt/doc/help.txt
generated
vendored
Normal file
8
WebUI/node_modules/mqtt/doc/help.txt
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
MQTT.js command line interface, available commands are:
|
||||
|
||||
* publish publish a message to the broker
|
||||
* subscribe subscribe for updates from the broker
|
||||
* version the current MQTT.js version
|
||||
* help help about commands
|
||||
|
||||
Launch 'mqtt help [command]' to know more about the commands.
|
||||
26
WebUI/node_modules/mqtt/doc/publish.txt
generated
vendored
Normal file
26
WebUI/node_modules/mqtt/doc/publish.txt
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Usage: mqtt publish [opts] topic [message]
|
||||
|
||||
Available options:
|
||||
|
||||
-h/--hostname HOST the broker host
|
||||
-p/--port PORT the broker port
|
||||
-i/--client-id ID the client id
|
||||
-q/--qos 0/1/2 the QoS of the message
|
||||
-t/--topic TOPIC the message topic
|
||||
-m/--message MSG the message body
|
||||
-r/--retain send a retained message
|
||||
-s/--stdin read the message body from stdin
|
||||
-M/--multiline read lines from stdin as multiple messages
|
||||
-u/--username USER the username
|
||||
-P/--password PASS the password
|
||||
-C/--protocol PROTO the protocol to use, 'mqtt',
|
||||
'mqtts', 'ws' or 'wss'
|
||||
--key PATH path to the key file
|
||||
--cert PATH path to the cert file
|
||||
--ca PATH path to the ca certificate
|
||||
--insecure do not verify the server certificate
|
||||
--will-topic TOPIC the will topic
|
||||
--will-payload BODY the will message
|
||||
--will-qos 0/1/2 the will qos
|
||||
--will-retain send a will retained message
|
||||
-H/--help show this
|
||||
26
WebUI/node_modules/mqtt/doc/subscribe.txt
generated
vendored
Normal file
26
WebUI/node_modules/mqtt/doc/subscribe.txt
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Usage: mqtt subscribe [opts] [topic]
|
||||
|
||||
Available options:
|
||||
|
||||
-h/--hostname HOST the broker host
|
||||
-p/--port PORT the broker port
|
||||
-i/--client-id ID the client id
|
||||
-q/--qos 0/1/2 the QoS of the message
|
||||
--no-clean do not discard any pending message for
|
||||
the given id
|
||||
-t/--topic TOPIC the message topic
|
||||
-k/--keepalive SEC send a ping every SEC seconds
|
||||
-u/--username USER the username
|
||||
-P/--password PASS the password
|
||||
-l/--protocol PROTO the protocol to use, 'mqtt',
|
||||
'mqtts', 'ws' or 'wss'
|
||||
--key PATH path to the key file
|
||||
--cert PATH path to the cert file
|
||||
--ca PATH path to the ca certificate
|
||||
--insecure do not verify the server certificate
|
||||
--will-topic TOPIC the will topic
|
||||
--will-message BODY the will message
|
||||
--will-qos 0/1/2 the will qos
|
||||
--will-retain send a will retained message
|
||||
-v/--verbose print the topic before the message
|
||||
-H/--help show this
|
||||
1897
WebUI/node_modules/mqtt/lib/client.js
generated
vendored
Normal file
1897
WebUI/node_modules/mqtt/lib/client.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
129
WebUI/node_modules/mqtt/lib/connect/ali.js
generated
vendored
Normal file
129
WebUI/node_modules/mqtt/lib/connect/ali.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
'use strict'
|
||||
|
||||
const { Buffer } = require('buffer')
|
||||
const Transform = require('readable-stream').Transform
|
||||
const duplexify = require('duplexify')
|
||||
|
||||
/* global FileReader */
|
||||
let my
|
||||
let proxy
|
||||
let stream
|
||||
let isInitialized = false
|
||||
|
||||
function buildProxy () {
|
||||
const proxy = new Transform()
|
||||
proxy._write = function (chunk, encoding, next) {
|
||||
my.sendSocketMessage({
|
||||
data: chunk.buffer,
|
||||
success: function () {
|
||||
next()
|
||||
},
|
||||
fail: function () {
|
||||
next(new Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
proxy._flush = function socketEnd (done) {
|
||||
my.closeSocket({
|
||||
success: function () {
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
function setDefaultOpts (opts) {
|
||||
if (!opts.hostname) {
|
||||
opts.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.path) {
|
||||
opts.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
opts.wsOptions = {}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUrl (opts, client) {
|
||||
const protocol = opts.protocol === 'alis' ? 'wss' : 'ws'
|
||||
let url = protocol + '://' + opts.hostname + opts.path
|
||||
if (opts.port && opts.port !== 80 && opts.port !== 443) {
|
||||
url = protocol + '://' + opts.hostname + ':' + opts.port + opts.path
|
||||
}
|
||||
if (typeof (opts.transformWsUrl) === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function bindEventHandler () {
|
||||
if (isInitialized) return
|
||||
|
||||
isInitialized = true
|
||||
|
||||
my.onSocketOpen(function () {
|
||||
stream.setReadable(proxy)
|
||||
stream.setWritable(proxy)
|
||||
stream.emit('connect')
|
||||
})
|
||||
|
||||
my.onSocketMessage(function (res) {
|
||||
if (typeof res.data === 'string') {
|
||||
const buffer = Buffer.from(res.data, 'base64')
|
||||
proxy.push(buffer)
|
||||
} else {
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener('load', function () {
|
||||
let data = reader.result
|
||||
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data, 'utf8')
|
||||
proxy.push(data)
|
||||
})
|
||||
reader.readAsArrayBuffer(res.data)
|
||||
}
|
||||
})
|
||||
|
||||
my.onSocketClose(function () {
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
})
|
||||
|
||||
my.onSocketError(function (res) {
|
||||
stream.destroy(res)
|
||||
})
|
||||
}
|
||||
|
||||
function buildStream (client, opts) {
|
||||
opts.hostname = opts.hostname || opts.host
|
||||
|
||||
if (!opts.hostname) {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
|
||||
const websocketSubProtocol =
|
||||
(opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
setDefaultOpts(opts)
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
my = opts.my
|
||||
my.connectSocket({
|
||||
url: url,
|
||||
protocols: websocketSubProtocol
|
||||
})
|
||||
|
||||
proxy = buildProxy()
|
||||
stream = duplexify.obj()
|
||||
|
||||
bindEventHandler()
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
module.exports = buildStream
|
||||
165
WebUI/node_modules/mqtt/lib/connect/index.js
generated
vendored
Normal file
165
WebUI/node_modules/mqtt/lib/connect/index.js
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
'use strict'
|
||||
|
||||
const MqttClient = require('../client')
|
||||
const Store = require('../store')
|
||||
const url = require('url')
|
||||
const xtend = require('xtend')
|
||||
const debug = require('debug')('mqttjs')
|
||||
|
||||
const protocols = {}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
if ((typeof process !== 'undefined' && process.title !== 'browser') || typeof __webpack_require__ !== 'function') {
|
||||
protocols.mqtt = require('./tcp')
|
||||
protocols.tcp = require('./tcp')
|
||||
protocols.ssl = require('./tls')
|
||||
protocols.tls = require('./tls')
|
||||
protocols.mqtts = require('./tls')
|
||||
} else {
|
||||
protocols.wx = require('./wx')
|
||||
protocols.wxs = require('./wx')
|
||||
|
||||
protocols.ali = require('./ali')
|
||||
protocols.alis = require('./ali')
|
||||
}
|
||||
|
||||
protocols.ws = require('./ws')
|
||||
protocols.wss = require('./ws')
|
||||
|
||||
/**
|
||||
* Parse the auth attribute and merge username and password in the options object.
|
||||
*
|
||||
* @param {Object} [opts] option object
|
||||
*/
|
||||
function parseAuthOptions (opts) {
|
||||
let matches
|
||||
if (opts.auth) {
|
||||
matches = opts.auth.match(/^(.+):(.+)$/)
|
||||
if (matches) {
|
||||
opts.username = matches[1]
|
||||
opts.password = matches[2]
|
||||
} else {
|
||||
opts.username = opts.auth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* connect - connect to an MQTT broker.
|
||||
*
|
||||
* @param {String} [brokerUrl] - url of the broker, optional
|
||||
* @param {Object} opts - see MqttClient#constructor
|
||||
*/
|
||||
function connect (brokerUrl, opts) {
|
||||
debug('connecting to an MQTT broker...')
|
||||
if ((typeof brokerUrl === 'object') && !opts) {
|
||||
opts = brokerUrl
|
||||
brokerUrl = null
|
||||
}
|
||||
|
||||
opts = opts || {}
|
||||
|
||||
if (brokerUrl) {
|
||||
// eslint-disable-next-line
|
||||
const parsed = url.parse(brokerUrl, true)
|
||||
if (parsed.port != null) {
|
||||
parsed.port = Number(parsed.port)
|
||||
}
|
||||
|
||||
opts = xtend(parsed, opts)
|
||||
|
||||
if (opts.protocol === null) {
|
||||
throw new Error('Missing protocol')
|
||||
}
|
||||
|
||||
opts.protocol = opts.protocol.replace(/:$/, '')
|
||||
}
|
||||
|
||||
// merge in the auth options if supplied
|
||||
parseAuthOptions(opts)
|
||||
|
||||
// support clientId passed in the query string of the url
|
||||
if (opts.query && typeof opts.query.clientId === 'string') {
|
||||
opts.clientId = opts.query.clientId
|
||||
}
|
||||
|
||||
if (opts.cert && opts.key) {
|
||||
if (opts.protocol) {
|
||||
if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) {
|
||||
switch (opts.protocol) {
|
||||
case 'mqtt':
|
||||
opts.protocol = 'mqtts'
|
||||
break
|
||||
case 'ws':
|
||||
opts.protocol = 'wss'
|
||||
break
|
||||
case 'wx':
|
||||
opts.protocol = 'wxs'
|
||||
break
|
||||
case 'ali':
|
||||
opts.protocol = 'alis'
|
||||
break
|
||||
default:
|
||||
throw new Error('Unknown protocol for secure connection: "' + opts.protocol + '"!')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A cert and key was provided, however no protocol was specified, so we will throw an error.
|
||||
throw new Error('Missing secure protocol key')
|
||||
}
|
||||
}
|
||||
|
||||
if (!protocols[opts.protocol]) {
|
||||
const isSecure = ['mqtts', 'wss'].indexOf(opts.protocol) !== -1
|
||||
opts.protocol = [
|
||||
'mqtt',
|
||||
'mqtts',
|
||||
'ws',
|
||||
'wss',
|
||||
'wx',
|
||||
'wxs',
|
||||
'ali',
|
||||
'alis'
|
||||
].filter(function (key, index) {
|
||||
if (isSecure && index % 2 === 0) {
|
||||
// Skip insecure protocols when requesting a secure one.
|
||||
return false
|
||||
}
|
||||
return (typeof protocols[key] === 'function')
|
||||
})[0]
|
||||
}
|
||||
|
||||
if (opts.clean === false && !opts.clientId) {
|
||||
throw new Error('Missing clientId for unclean clients')
|
||||
}
|
||||
|
||||
if (opts.protocol) {
|
||||
opts.defaultProtocol = opts.protocol
|
||||
}
|
||||
|
||||
function wrapper (client) {
|
||||
if (opts.servers) {
|
||||
if (!client._reconnectCount || client._reconnectCount === opts.servers.length) {
|
||||
client._reconnectCount = 0
|
||||
}
|
||||
|
||||
opts.host = opts.servers[client._reconnectCount].host
|
||||
opts.port = opts.servers[client._reconnectCount].port
|
||||
opts.protocol = (!opts.servers[client._reconnectCount].protocol ? opts.defaultProtocol : opts.servers[client._reconnectCount].protocol)
|
||||
opts.hostname = opts.host
|
||||
|
||||
client._reconnectCount++
|
||||
}
|
||||
|
||||
debug('calling streambuilder for', opts.protocol)
|
||||
return protocols[opts.protocol](client, opts)
|
||||
}
|
||||
const client = new MqttClient(wrapper, opts)
|
||||
client.on('error', function () { /* Automatically set up client error handling */ })
|
||||
return client
|
||||
}
|
||||
|
||||
module.exports = connect
|
||||
module.exports.connect = connect
|
||||
module.exports.MqttClient = MqttClient
|
||||
module.exports.Store = Store
|
||||
20
WebUI/node_modules/mqtt/lib/connect/tcp.js
generated
vendored
Normal file
20
WebUI/node_modules/mqtt/lib/connect/tcp.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict'
|
||||
const net = require('net')
|
||||
const debug = require('debug')('mqttjs:tcp')
|
||||
|
||||
/*
|
||||
variables port and host can be removed since
|
||||
you have all required information in opts object
|
||||
*/
|
||||
function streamBuilder (client, opts) {
|
||||
opts.port = opts.port || 1883
|
||||
opts.hostname = opts.hostname || opts.host || 'localhost'
|
||||
|
||||
const port = opts.port
|
||||
const host = opts.hostname
|
||||
|
||||
debug('port %d and host %s', port, host)
|
||||
return net.createConnection(port, host)
|
||||
}
|
||||
|
||||
module.exports = streamBuilder
|
||||
48
WebUI/node_modules/mqtt/lib/connect/tls.js
generated
vendored
Normal file
48
WebUI/node_modules/mqtt/lib/connect/tls.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict'
|
||||
const tls = require('tls')
|
||||
const net = require('net')
|
||||
const debug = require('debug')('mqttjs:tls')
|
||||
|
||||
function buildBuilder (mqttClient, opts) {
|
||||
opts.port = opts.port || 8883
|
||||
opts.host = opts.hostname || opts.host || 'localhost'
|
||||
|
||||
if (net.isIP(opts.host) === 0) {
|
||||
opts.servername = opts.host
|
||||
}
|
||||
|
||||
opts.rejectUnauthorized = opts.rejectUnauthorized !== false
|
||||
|
||||
delete opts.path
|
||||
|
||||
debug('port %d host %s rejectUnauthorized %b', opts.port, opts.host, opts.rejectUnauthorized)
|
||||
|
||||
const connection = tls.connect(opts)
|
||||
/* eslint no-use-before-define: [2, "nofunc"] */
|
||||
connection.on('secureConnect', function () {
|
||||
if (opts.rejectUnauthorized && !connection.authorized) {
|
||||
connection.emit('error', new Error('TLS not authorized'))
|
||||
} else {
|
||||
connection.removeListener('error', handleTLSerrors)
|
||||
}
|
||||
})
|
||||
|
||||
function handleTLSerrors (err) {
|
||||
// How can I get verify this error is a tls error?
|
||||
if (opts.rejectUnauthorized) {
|
||||
mqttClient.emit('error', err)
|
||||
}
|
||||
|
||||
// close this connection to match the behaviour of net
|
||||
// otherwise all we get is an error from the connection
|
||||
// and close event doesn't fire. This is a work around
|
||||
// to enable the reconnect code to work the same as with
|
||||
// net.createConnection
|
||||
connection.end()
|
||||
}
|
||||
|
||||
connection.on('error', handleTLSerrors)
|
||||
return connection
|
||||
}
|
||||
|
||||
module.exports = buildBuilder
|
||||
257
WebUI/node_modules/mqtt/lib/connect/ws.js
generated
vendored
Normal file
257
WebUI/node_modules/mqtt/lib/connect/ws.js
generated
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
'use strict'
|
||||
|
||||
const { Buffer } = require('buffer')
|
||||
const WS = require('ws')
|
||||
const debug = require('debug')('mqttjs:ws')
|
||||
const duplexify = require('duplexify')
|
||||
const Transform = require('readable-stream').Transform
|
||||
|
||||
const WSS_OPTIONS = [
|
||||
'rejectUnauthorized',
|
||||
'ca',
|
||||
'cert',
|
||||
'key',
|
||||
'pfx',
|
||||
'passphrase'
|
||||
]
|
||||
// eslint-disable-next-line camelcase
|
||||
const IS_BROWSER = (typeof process !== 'undefined' && process.title === 'browser') || typeof __webpack_require__ === 'function'
|
||||
function buildUrl (opts, client) {
|
||||
let url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path
|
||||
if (typeof (opts.transformWsUrl) === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function setDefaultOpts (opts) {
|
||||
const options = opts
|
||||
if (!opts.hostname) {
|
||||
options.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.port) {
|
||||
if (opts.protocol === 'wss') {
|
||||
options.port = 443
|
||||
} else {
|
||||
options.port = 80
|
||||
}
|
||||
}
|
||||
if (!opts.path) {
|
||||
options.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
options.wsOptions = {}
|
||||
}
|
||||
if (!IS_BROWSER && opts.protocol === 'wss') {
|
||||
// Add cert/key/ca etc options
|
||||
WSS_OPTIONS.forEach(function (prop) {
|
||||
if (Object.prototype.hasOwnProperty.call(opts, prop) && !Object.prototype.hasOwnProperty.call(opts.wsOptions, prop)) {
|
||||
options.wsOptions[prop] = opts[prop]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function setDefaultBrowserOpts (opts) {
|
||||
const options = setDefaultOpts(opts)
|
||||
|
||||
if (!options.hostname) {
|
||||
options.hostname = options.host
|
||||
}
|
||||
|
||||
if (!options.hostname) {
|
||||
// Throwing an error in a Web Worker if no `hostname` is given, because we
|
||||
// can not determine the `hostname` automatically. If connecting to
|
||||
// localhost, please supply the `hostname` as an argument.
|
||||
if (typeof (document) === 'undefined') {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
const parsed = new URL(document.URL)
|
||||
options.hostname = parsed.hostname
|
||||
|
||||
if (!options.port) {
|
||||
options.port = parsed.port
|
||||
}
|
||||
}
|
||||
|
||||
// objectMode should be defined for logic
|
||||
if (options.objectMode === undefined) {
|
||||
options.objectMode = !(options.binary === true || options.binary === undefined)
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function createWebSocket (client, url, opts) {
|
||||
debug('createWebSocket')
|
||||
debug('protocol: ' + opts.protocolId + ' ' + opts.protocolVersion)
|
||||
const websocketSubProtocol =
|
||||
(opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
debug('creating new Websocket for url: ' + url + ' and protocol: ' + websocketSubProtocol)
|
||||
const socket = new WS(url, [websocketSubProtocol], opts.wsOptions)
|
||||
return socket
|
||||
}
|
||||
|
||||
function createBrowserWebSocket (client, opts) {
|
||||
const websocketSubProtocol =
|
||||
(opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
/* global WebSocket */
|
||||
const socket = new WebSocket(url, [websocketSubProtocol])
|
||||
socket.binaryType = 'arraybuffer'
|
||||
return socket
|
||||
}
|
||||
|
||||
function streamBuilder (client, opts) {
|
||||
debug('streamBuilder')
|
||||
const options = setDefaultOpts(opts)
|
||||
const url = buildUrl(options, client)
|
||||
const socket = createWebSocket(client, url, options)
|
||||
const webSocketStream = WS.createWebSocketStream(socket, options.wsOptions)
|
||||
webSocketStream.url = url
|
||||
socket.on('close', () => { webSocketStream.destroy() })
|
||||
return webSocketStream
|
||||
}
|
||||
|
||||
function browserStreamBuilder (client, opts) {
|
||||
debug('browserStreamBuilder')
|
||||
let stream
|
||||
const options = setDefaultBrowserOpts(opts)
|
||||
// sets the maximum socket buffer size before throttling
|
||||
const bufferSize = options.browserBufferSize || 1024 * 512
|
||||
|
||||
const bufferTimeout = opts.browserBufferTimeout || 1000
|
||||
|
||||
const coerceToBuffer = !opts.objectMode
|
||||
|
||||
const socket = createBrowserWebSocket(client, opts)
|
||||
|
||||
const proxy = buildProxy(opts, socketWriteBrowser, socketEndBrowser)
|
||||
|
||||
if (!opts.objectMode) {
|
||||
proxy._writev = writev
|
||||
}
|
||||
proxy.on('close', () => { socket.close() })
|
||||
|
||||
const eventListenerSupport = (typeof socket.addEventListener !== 'undefined')
|
||||
|
||||
// was already open when passed in
|
||||
if (socket.readyState === socket.OPEN) {
|
||||
stream = proxy
|
||||
} else {
|
||||
stream = stream = duplexify(undefined, undefined, opts)
|
||||
if (!opts.objectMode) {
|
||||
stream._writev = writev
|
||||
}
|
||||
|
||||
if (eventListenerSupport) {
|
||||
socket.addEventListener('open', onopen)
|
||||
} else {
|
||||
socket.onopen = onopen
|
||||
}
|
||||
}
|
||||
|
||||
stream.socket = socket
|
||||
|
||||
if (eventListenerSupport) {
|
||||
socket.addEventListener('close', onclose)
|
||||
socket.addEventListener('error', onerror)
|
||||
socket.addEventListener('message', onmessage)
|
||||
} else {
|
||||
socket.onclose = onclose
|
||||
socket.onerror = onerror
|
||||
socket.onmessage = onmessage
|
||||
}
|
||||
|
||||
// methods for browserStreamBuilder
|
||||
|
||||
function buildProxy (options, socketWrite, socketEnd) {
|
||||
const proxy = new Transform({
|
||||
objectModeMode: options.objectMode
|
||||
})
|
||||
|
||||
proxy._write = socketWrite
|
||||
proxy._flush = socketEnd
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
function onopen () {
|
||||
stream.setReadable(proxy)
|
||||
stream.setWritable(proxy)
|
||||
stream.emit('connect')
|
||||
}
|
||||
|
||||
function onclose () {
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
}
|
||||
|
||||
function onerror (err) {
|
||||
stream.destroy(err)
|
||||
}
|
||||
|
||||
function onmessage (event) {
|
||||
let data = event.data
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data, 'utf8')
|
||||
proxy.push(data)
|
||||
}
|
||||
|
||||
// this is to be enabled only if objectMode is false
|
||||
function writev (chunks, cb) {
|
||||
const buffers = new Array(chunks.length)
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
if (typeof chunks[i].chunk === 'string') {
|
||||
buffers[i] = Buffer.from(chunks[i], 'utf8')
|
||||
} else {
|
||||
buffers[i] = chunks[i].chunk
|
||||
}
|
||||
}
|
||||
|
||||
this._write(Buffer.concat(buffers), 'binary', cb)
|
||||
}
|
||||
|
||||
function socketWriteBrowser (chunk, enc, next) {
|
||||
if (socket.bufferedAmount > bufferSize) {
|
||||
// throttle data until buffered amount is reduced.
|
||||
setTimeout(socketWriteBrowser, bufferTimeout, chunk, enc, next)
|
||||
}
|
||||
|
||||
if (coerceToBuffer && typeof chunk === 'string') {
|
||||
chunk = Buffer.from(chunk, 'utf8')
|
||||
}
|
||||
|
||||
try {
|
||||
socket.send(chunk)
|
||||
} catch (err) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
function socketEndBrowser (done) {
|
||||
socket.close()
|
||||
done()
|
||||
}
|
||||
|
||||
// end methods for browserStreamBuilder
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
if (IS_BROWSER) {
|
||||
module.exports = browserStreamBuilder
|
||||
} else {
|
||||
module.exports = streamBuilder
|
||||
}
|
||||
133
WebUI/node_modules/mqtt/lib/connect/wx.js
generated
vendored
Normal file
133
WebUI/node_modules/mqtt/lib/connect/wx.js
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
'use strict'
|
||||
|
||||
const { Buffer } = require('buffer')
|
||||
const Transform = require('readable-stream').Transform
|
||||
const duplexify = require('duplexify')
|
||||
|
||||
/* global wx */
|
||||
let socketTask, proxy, stream
|
||||
|
||||
function buildProxy () {
|
||||
const proxy = new Transform()
|
||||
proxy._write = function (chunk, encoding, next) {
|
||||
socketTask.send({
|
||||
data: chunk.buffer,
|
||||
success: function () {
|
||||
next()
|
||||
},
|
||||
fail: function (errMsg) {
|
||||
next(new Error(errMsg))
|
||||
}
|
||||
})
|
||||
}
|
||||
proxy._flush = function socketEnd (done) {
|
||||
socketTask.close({
|
||||
success: function () {
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
function setDefaultOpts (opts) {
|
||||
if (!opts.hostname) {
|
||||
opts.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.path) {
|
||||
opts.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
opts.wsOptions = {}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUrl (opts, client) {
|
||||
const protocol = opts.protocol === 'wxs' ? 'wss' : 'ws'
|
||||
let url = protocol + '://' + opts.hostname + opts.path
|
||||
if (opts.port && opts.port !== 80 && opts.port !== 443) {
|
||||
url = protocol + '://' + opts.hostname + ':' + opts.port + opts.path
|
||||
}
|
||||
if (typeof (opts.transformWsUrl) === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function bindEventHandler () {
|
||||
socketTask.onOpen(function () {
|
||||
stream.setReadable(proxy)
|
||||
stream.setWritable(proxy)
|
||||
stream.emit('connect')
|
||||
})
|
||||
|
||||
socketTask.onMessage(function (res) {
|
||||
let data = res.data
|
||||
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data, 'utf8')
|
||||
proxy.push(data)
|
||||
})
|
||||
|
||||
socketTask.onClose(function () {
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
})
|
||||
|
||||
socketTask.onError(function (res) {
|
||||
stream.destroy(new Error(res.errMsg))
|
||||
})
|
||||
}
|
||||
|
||||
function buildStream (client, opts) {
|
||||
opts.hostname = opts.hostname || opts.host
|
||||
|
||||
if (!opts.hostname) {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
|
||||
const websocketSubProtocol =
|
||||
(opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
setDefaultOpts(opts)
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
socketTask = wx.connectSocket({
|
||||
url: url,
|
||||
protocols: [websocketSubProtocol]
|
||||
})
|
||||
|
||||
proxy = buildProxy()
|
||||
stream = duplexify.obj()
|
||||
stream._destroy = function (err, cb) {
|
||||
socketTask.close({
|
||||
success: function () {
|
||||
cb && cb(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const destroyRef = stream.destroy
|
||||
stream.destroy = function () {
|
||||
stream.destroy = destroyRef
|
||||
|
||||
const self = this
|
||||
setTimeout(function () {
|
||||
socketTask.close({
|
||||
fail: function () {
|
||||
self._destroy(new Error())
|
||||
}
|
||||
})
|
||||
}, 0)
|
||||
}.bind(stream)
|
||||
|
||||
bindEventHandler()
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
module.exports = buildStream
|
||||
69
WebUI/node_modules/mqtt/lib/default-message-id-provider.js
generated
vendored
Normal file
69
WebUI/node_modules/mqtt/lib/default-message-id-provider.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* DefaultMessageAllocator constructor
|
||||
* @constructor
|
||||
*/
|
||||
function DefaultMessageIdProvider () {
|
||||
if (!(this instanceof DefaultMessageIdProvider)) {
|
||||
return new DefaultMessageIdProvider()
|
||||
}
|
||||
|
||||
/**
|
||||
* MessageIDs starting with 1
|
||||
* ensure that nextId is min. 1, see https://github.com/mqttjs/MQTT.js/issues/810
|
||||
*/
|
||||
this.nextId = Math.max(1, Math.floor(Math.random() * 65535))
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate
|
||||
*
|
||||
* Get the next messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
DefaultMessageIdProvider.prototype.allocate = function () {
|
||||
// id becomes current state of this.nextId and increments afterwards
|
||||
const id = this.nextId++
|
||||
// Ensure 16 bit unsigned int (max 65535, nextId got one higher)
|
||||
if (this.nextId === 65536) {
|
||||
this.nextId = 1
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastAllocated
|
||||
* Get the last allocated messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
DefaultMessageIdProvider.prototype.getLastAllocated = function () {
|
||||
return (this.nextId === 1) ? 65535 : (this.nextId - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* register
|
||||
* Register messageId. If success return true, otherwise return false.
|
||||
* @param { unsigned int } - messageId to register,
|
||||
* @return boolean
|
||||
*/
|
||||
DefaultMessageIdProvider.prototype.register = function (messageId) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* deallocate
|
||||
* Deallocate messageId.
|
||||
* @param { unsigned int } - messageId to deallocate,
|
||||
*/
|
||||
DefaultMessageIdProvider.prototype.deallocate = function (messageId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* clear
|
||||
* Deallocate all messageIds.
|
||||
*/
|
||||
DefaultMessageIdProvider.prototype.clear = function () {
|
||||
}
|
||||
|
||||
module.exports = DefaultMessageIdProvider
|
||||
128
WebUI/node_modules/mqtt/lib/store.js
generated
vendored
Normal file
128
WebUI/node_modules/mqtt/lib/store.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
const xtend = require('xtend')
|
||||
|
||||
const Readable = require('readable-stream').Readable
|
||||
const streamsOpts = { objectMode: true }
|
||||
const defaultStoreOptions = {
|
||||
clean: true
|
||||
}
|
||||
|
||||
/**
|
||||
* In-memory implementation of the message store
|
||||
* This can actually be saved into files.
|
||||
*
|
||||
* @param {Object} [options] - store options
|
||||
*/
|
||||
function Store (options) {
|
||||
if (!(this instanceof Store)) {
|
||||
return new Store(options)
|
||||
}
|
||||
|
||||
this.options = options || {}
|
||||
|
||||
// Defaults
|
||||
this.options = xtend(defaultStoreOptions, options)
|
||||
|
||||
this._inflights = new Map()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a packet to the store, a packet is
|
||||
* anything that has a messageId property.
|
||||
*
|
||||
*/
|
||||
Store.prototype.put = function (packet, cb) {
|
||||
this._inflights.set(packet.messageId, packet)
|
||||
|
||||
if (cb) {
|
||||
cb()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream with all the packets in the store
|
||||
*
|
||||
*/
|
||||
Store.prototype.createStream = function () {
|
||||
const stream = new Readable(streamsOpts)
|
||||
const values = []
|
||||
let destroyed = false
|
||||
let i = 0
|
||||
|
||||
this._inflights.forEach(function (value, key) {
|
||||
values.push(value)
|
||||
})
|
||||
|
||||
stream._read = function () {
|
||||
if (!destroyed && i < values.length) {
|
||||
this.push(values[i++])
|
||||
} else {
|
||||
this.push(null)
|
||||
}
|
||||
}
|
||||
|
||||
stream.destroy = function () {
|
||||
if (destroyed) {
|
||||
return
|
||||
}
|
||||
|
||||
const self = this
|
||||
|
||||
destroyed = true
|
||||
|
||||
setTimeout(function () {
|
||||
self.emit('close')
|
||||
}, 0)
|
||||
}
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a packet from the store.
|
||||
*/
|
||||
Store.prototype.del = function (packet, cb) {
|
||||
packet = this._inflights.get(packet.messageId)
|
||||
if (packet) {
|
||||
this._inflights.delete(packet.messageId)
|
||||
cb(null, packet)
|
||||
} else if (cb) {
|
||||
cb(new Error('missing packet'))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* get a packet from the store.
|
||||
*/
|
||||
Store.prototype.get = function (packet, cb) {
|
||||
packet = this._inflights.get(packet.messageId)
|
||||
if (packet) {
|
||||
cb(null, packet)
|
||||
} else if (cb) {
|
||||
cb(new Error('missing packet'))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the store
|
||||
*/
|
||||
Store.prototype.close = function (cb) {
|
||||
if (this.options.clean) {
|
||||
this._inflights = null
|
||||
}
|
||||
if (cb) {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Store
|
||||
47
WebUI/node_modules/mqtt/lib/topic-alias-recv.js
generated
vendored
Normal file
47
WebUI/node_modules/mqtt/lib/topic-alias-recv.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Topic Alias receiving manager
|
||||
* This holds alias to topic map
|
||||
* @param {Number} [max] - topic alias maximum entries
|
||||
*/
|
||||
function TopicAliasRecv (max) {
|
||||
if (!(this instanceof TopicAliasRecv)) {
|
||||
return new TopicAliasRecv(max)
|
||||
}
|
||||
this.aliasToTopic = {}
|
||||
this.max = max
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update topic - alias entry.
|
||||
* @param {String} [topic] - topic
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {Boolean} - if success return true otherwise false
|
||||
*/
|
||||
TopicAliasRecv.prototype.put = function (topic, alias) {
|
||||
if (alias === 0 || alias > this.max) {
|
||||
return false
|
||||
}
|
||||
this.aliasToTopic[alias] = topic
|
||||
this.length = Object.keys(this.aliasToTopic).length
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {String} [topic] - topic
|
||||
* @returns {Number} - if mapped topic exists return topic alias, otherwise return undefined
|
||||
*/
|
||||
TopicAliasRecv.prototype.getTopicByAlias = function (alias) {
|
||||
return this.aliasToTopic[alias]
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all entries
|
||||
*/
|
||||
TopicAliasRecv.prototype.clear = function () {
|
||||
this.aliasToTopic = {}
|
||||
}
|
||||
|
||||
module.exports = TopicAliasRecv
|
||||
91
WebUI/node_modules/mqtt/lib/topic-alias-send.js
generated
vendored
Normal file
91
WebUI/node_modules/mqtt/lib/topic-alias-send.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
const LruMap = require('lru-cache')
|
||||
const NumberAllocator = require('number-allocator').NumberAllocator
|
||||
|
||||
/**
|
||||
* Topic Alias sending manager
|
||||
* This holds both topic to alias and alias to topic map
|
||||
* @param {Number} [max] - topic alias maximum entries
|
||||
*/
|
||||
function TopicAliasSend (max) {
|
||||
if (!(this instanceof TopicAliasSend)) {
|
||||
return new TopicAliasSend(max)
|
||||
}
|
||||
|
||||
if (max > 0) {
|
||||
this.aliasToTopic = new LruMap({ max: max })
|
||||
this.topicToAlias = {}
|
||||
this.numberAllocator = new NumberAllocator(1, max)
|
||||
this.max = max
|
||||
this.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update topic - alias entry.
|
||||
* @param {String} [topic] - topic
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {Boolean} - if success return true otherwise false
|
||||
*/
|
||||
TopicAliasSend.prototype.put = function (topic, alias) {
|
||||
if (alias === 0 || alias > this.max) {
|
||||
return false
|
||||
}
|
||||
const entry = this.aliasToTopic.get(alias)
|
||||
if (entry) {
|
||||
delete this.topicToAlias[entry]
|
||||
}
|
||||
this.aliasToTopic.set(alias, topic)
|
||||
this.topicToAlias[topic] = alias
|
||||
this.numberAllocator.use(alias)
|
||||
this.length = this.aliasToTopic.length
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {String} - if mapped topic exists return topic, otherwise return undefined
|
||||
*/
|
||||
TopicAliasSend.prototype.getTopicByAlias = function (alias) {
|
||||
return this.aliasToTopic.get(alias)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {String} [topic] - topic
|
||||
* @returns {Number} - if mapped topic exists return topic alias, otherwise return undefined
|
||||
*/
|
||||
TopicAliasSend.prototype.getAliasByTopic = function (topic) {
|
||||
const alias = this.topicToAlias[topic]
|
||||
if (typeof alias !== 'undefined') {
|
||||
this.aliasToTopic.get(alias) // LRU update
|
||||
}
|
||||
return alias
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all entries
|
||||
*/
|
||||
TopicAliasSend.prototype.clear = function () {
|
||||
this.aliasToTopic.reset()
|
||||
this.topicToAlias = {}
|
||||
this.numberAllocator.clear()
|
||||
this.length = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Least Recently Used (LRU) topic alias
|
||||
* @returns {Number} - if vacant alias exists then return it, otherwise then return LRU alias
|
||||
*/
|
||||
TopicAliasSend.prototype.getLruAlias = function () {
|
||||
const alias = this.numberAllocator.firstVacant()
|
||||
if (alias) return alias
|
||||
return this.aliasToTopic.keys()[this.aliasToTopic.length - 1]
|
||||
}
|
||||
|
||||
module.exports = TopicAliasSend
|
||||
65
WebUI/node_modules/mqtt/lib/unique-message-id-provider.js
generated
vendored
Normal file
65
WebUI/node_modules/mqtt/lib/unique-message-id-provider.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict'
|
||||
|
||||
const NumberAllocator = require('number-allocator').NumberAllocator
|
||||
|
||||
/**
|
||||
* UniqueMessageAllocator constructor
|
||||
* @constructor
|
||||
*/
|
||||
function UniqueMessageIdProvider () {
|
||||
if (!(this instanceof UniqueMessageIdProvider)) {
|
||||
return new UniqueMessageIdProvider()
|
||||
}
|
||||
|
||||
this.numberAllocator = new NumberAllocator(1, 65535)
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate
|
||||
*
|
||||
* Get the next messageId.
|
||||
* @return if messageId is fully allocated then return null,
|
||||
* otherwise return the smallest usable unsigned int messageId.
|
||||
*/
|
||||
UniqueMessageIdProvider.prototype.allocate = function () {
|
||||
this.lastId = this.numberAllocator.alloc()
|
||||
return this.lastId
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastAllocated
|
||||
* Get the last allocated messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
UniqueMessageIdProvider.prototype.getLastAllocated = function () {
|
||||
return this.lastId
|
||||
}
|
||||
|
||||
/**
|
||||
* register
|
||||
* Register messageId. If success return true, otherwise return false.
|
||||
* @param { unsigned int } - messageId to register,
|
||||
* @return boolean
|
||||
*/
|
||||
UniqueMessageIdProvider.prototype.register = function (messageId) {
|
||||
return this.numberAllocator.use(messageId)
|
||||
}
|
||||
|
||||
/**
|
||||
* deallocate
|
||||
* Deallocate messageId.
|
||||
* @param { unsigned int } - messageId to deallocate,
|
||||
*/
|
||||
UniqueMessageIdProvider.prototype.deallocate = function (messageId) {
|
||||
this.numberAllocator.free(messageId)
|
||||
}
|
||||
|
||||
/**
|
||||
* clear
|
||||
* Deallocate all messageIds.
|
||||
*/
|
||||
UniqueMessageIdProvider.prototype.clear = function () {
|
||||
this.numberAllocator.clear()
|
||||
}
|
||||
|
||||
module.exports = UniqueMessageIdProvider
|
||||
52
WebUI/node_modules/mqtt/lib/validations.js
generated
vendored
Normal file
52
WebUI/node_modules/mqtt/lib/validations.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Validate a topic to see if it's valid or not.
|
||||
* A topic is valid if it follow below rules:
|
||||
* - Rule #1: If any part of the topic is not `+` or `#`, then it must not contain `+` and '#'
|
||||
* - Rule #2: Part `#` must be located at the end of the mailbox
|
||||
*
|
||||
* @param {String} topic - A topic
|
||||
* @returns {Boolean} If the topic is valid, returns true. Otherwise, returns false.
|
||||
*/
|
||||
function validateTopic (topic) {
|
||||
const parts = topic.split('/')
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (parts[i] === '+') {
|
||||
continue
|
||||
}
|
||||
|
||||
if (parts[i] === '#') {
|
||||
// for Rule #2
|
||||
return i === parts.length - 1
|
||||
}
|
||||
|
||||
if (parts[i].indexOf('+') !== -1 || parts[i].indexOf('#') !== -1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of topics to see if any of them is valid or not
|
||||
* @param {Array} topics - Array of topics
|
||||
* @returns {String} If the topics is valid, returns null. Otherwise, returns the invalid one
|
||||
*/
|
||||
function validateTopics (topics) {
|
||||
if (topics.length === 0) {
|
||||
return 'empty_topic_list'
|
||||
}
|
||||
for (let i = 0; i < topics.length; i++) {
|
||||
if (!validateTopic(topics[i])) {
|
||||
return topics[i]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateTopics: validateTopics
|
||||
}
|
||||
21
WebUI/node_modules/mqtt/mqtt.js
generated
vendored
Normal file
21
WebUI/node_modules/mqtt/mqtt.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2015 MQTT.js contributors.
|
||||
* Copyright (c) 2011-2014 Adam Rudd.
|
||||
*
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
|
||||
const MqttClient = require('./lib/client')
|
||||
const connect = require('./lib/connect')
|
||||
const Store = require('./lib/store')
|
||||
const DefaultMessageIdProvider = require('./lib/default-message-id-provider')
|
||||
const UniqueMessageIdProvider = require('./lib/unique-message-id-provider')
|
||||
|
||||
module.exports.connect = connect
|
||||
|
||||
// Expose MqttClient
|
||||
module.exports.MqttClient = MqttClient
|
||||
module.exports.Client = MqttClient
|
||||
module.exports.Store = Store
|
||||
module.exports.DefaultMessageIdProvider = DefaultMessageIdProvider
|
||||
module.exports.UniqueMessageIdProvider = UniqueMessageIdProvider
|
||||
20
WebUI/node_modules/mqtt/node_modules/debug/LICENSE
generated
vendored
Normal file
20
WebUI/node_modules/mqtt/node_modules/debug/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2018-2021 Josh Junon
|
||||
|
||||
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.
|
||||
|
||||
481
WebUI/node_modules/mqtt/node_modules/debug/README.md
generated
vendored
Normal file
481
WebUI/node_modules/mqtt/node_modules/debug/README.md
generated
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
# debug
|
||||
[](https://travis-ci.org/debug-js/debug) [](https://coveralls.io/github/debug-js/debug?branch=master) [](https://visionmedia-community-slackin.now.sh/) [](#backers)
|
||||
[](#sponsors)
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||
|
||||
A tiny JavaScript debugging utility modelled after Node.js core's debugging
|
||||
technique. Works in Node.js and web browsers.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install debug
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
|
||||
|
||||
Example [_app.js_](./examples/node/app.js):
|
||||
|
||||
```js
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %o', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
||||
```
|
||||
|
||||
Example [_worker.js_](./examples/node/worker.js):
|
||||
|
||||
```js
|
||||
var a = require('debug')('worker:a')
|
||||
, b = require('debug')('worker:b');
|
||||
|
||||
function work() {
|
||||
a('doing lots of uninteresting work');
|
||||
setTimeout(work, Math.random() * 1000);
|
||||
}
|
||||
|
||||
work();
|
||||
|
||||
function workb() {
|
||||
b('doing some work');
|
||||
setTimeout(workb, Math.random() * 2000);
|
||||
}
|
||||
|
||||
workb();
|
||||
```
|
||||
|
||||
The `DEBUG` environment variable is then used to enable these based on space or
|
||||
comma-delimited names.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
|
||||
|
||||
#### Windows command prompt notes
|
||||
|
||||
##### CMD
|
||||
|
||||
On Windows the environment variable is set using the `set` command.
|
||||
|
||||
```cmd
|
||||
set DEBUG=*,-not_this
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```cmd
|
||||
set DEBUG=* & node app.js
|
||||
```
|
||||
|
||||
##### PowerShell (VS Code default)
|
||||
|
||||
PowerShell uses different syntax to set environment variables.
|
||||
|
||||
```cmd
|
||||
$env:DEBUG = "*,-not_this"
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```cmd
|
||||
$env:DEBUG='app';node app.js
|
||||
```
|
||||
|
||||
Then, run the program to be debugged as usual.
|
||||
|
||||
npm script example:
|
||||
```js
|
||||
"windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
|
||||
```
|
||||
|
||||
## Namespace Colors
|
||||
|
||||
Every debug instance has a color generated for it based on its namespace name.
|
||||
This helps when visually parsing the debug output to identify which debug instance
|
||||
a debug line belongs to.
|
||||
|
||||
#### Node.js
|
||||
|
||||
In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
|
||||
the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
|
||||
otherwise debug will only use a small handful of basic colors.
|
||||
|
||||
<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
|
||||
|
||||
#### Web Browser
|
||||
|
||||
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
|
||||
option. These are WebKit web inspectors, Firefox ([since version
|
||||
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
|
||||
and the Firebug plugin for Firefox (any version).
|
||||
|
||||
<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
|
||||
|
||||
|
||||
## Millisecond diff
|
||||
|
||||
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||
|
||||
When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png">
|
||||
|
||||
|
||||
## Conventions
|
||||
|
||||
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
|
||||
|
||||
## Wildcards
|
||||
|
||||
The `*` character may be used as a wildcard. Suppose for example your library has
|
||||
debuggers named "connect:bodyParser", "connect:compress", "connect:session",
|
||||
instead of listing all three with
|
||||
`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
|
||||
`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
|
||||
|
||||
You can also exclude specific debuggers by prefixing them with a "-" character.
|
||||
For example, `DEBUG=*,-connect:*` would include all debuggers except those
|
||||
starting with "connect:".
|
||||
|
||||
## Environment Variables
|
||||
|
||||
When running through Node.js, you can set a few environment variables that will
|
||||
change the behavior of the debug logging:
|
||||
|
||||
| Name | Purpose |
|
||||
|-----------|-------------------------------------------------|
|
||||
| `DEBUG` | Enables/disables specific debugging namespaces. |
|
||||
| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). |
|
||||
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
|
||||
| `DEBUG_DEPTH` | Object inspection depth. |
|
||||
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
|
||||
|
||||
|
||||
__Note:__ The environment variables beginning with `DEBUG_` end up being
|
||||
converted into an Options object that gets used with `%o`/`%O` formatters.
|
||||
See the Node.js documentation for
|
||||
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
|
||||
for the complete list.
|
||||
|
||||
## Formatters
|
||||
|
||||
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
|
||||
Below are the officially supported formatters:
|
||||
|
||||
| Formatter | Representation |
|
||||
|-----------|----------------|
|
||||
| `%O` | Pretty-print an Object on multiple lines. |
|
||||
| `%o` | Pretty-print an Object all on a single line. |
|
||||
| `%s` | String. |
|
||||
| `%d` | Number (both integer and float). |
|
||||
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
|
||||
| `%%` | Single percent sign ('%'). This does not consume an argument. |
|
||||
|
||||
|
||||
### Custom formatters
|
||||
|
||||
You can add custom formatters by extending the `debug.formatters` object.
|
||||
For example, if you wanted to add support for rendering a Buffer as hex with
|
||||
`%h`, you could do something like:
|
||||
|
||||
```js
|
||||
const createDebug = require('debug')
|
||||
createDebug.formatters.h = (v) => {
|
||||
return v.toString('hex')
|
||||
}
|
||||
|
||||
// …elsewhere
|
||||
const debug = createDebug('foo')
|
||||
debug('this is hex: %h', new Buffer('hello world'))
|
||||
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
|
||||
```
|
||||
|
||||
|
||||
## Browser Support
|
||||
|
||||
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
|
||||
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
|
||||
if you don't want to build it yourself.
|
||||
|
||||
Debug's enable state is currently persisted by `localStorage`.
|
||||
Consider the situation shown below where you have `worker:a` and `worker:b`,
|
||||
and wish to debug both. You can enable this using `localStorage.debug`:
|
||||
|
||||
```js
|
||||
localStorage.debug = 'worker:*'
|
||||
```
|
||||
|
||||
And then refresh the page.
|
||||
|
||||
```js
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
b('doing some work');
|
||||
}, 1200);
|
||||
```
|
||||
|
||||
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_.
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/7143133/152083257-29034707-c42c-4959-8add-3cee850e6fcf.png">
|
||||
|
||||
## Output streams
|
||||
|
||||
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
|
||||
|
||||
Example [_stdout.js_](./examples/node/stdout.js):
|
||||
|
||||
```js
|
||||
var debug = require('debug');
|
||||
var error = debug('app:error');
|
||||
|
||||
// by default stderr is used
|
||||
error('goes to stderr!');
|
||||
|
||||
var log = debug('app:log');
|
||||
// set this namespace to log via console.log
|
||||
log.log = console.log.bind(console); // don't forget to bind to console!
|
||||
log('goes to stdout');
|
||||
error('still goes to stderr!');
|
||||
|
||||
// set all output to go via console.info
|
||||
// overrides all per-namespace log settings
|
||||
debug.log = console.info.bind(console);
|
||||
error('now goes to stdout via console.info');
|
||||
log('still goes to stdout, but via console.info now');
|
||||
```
|
||||
|
||||
## Extend
|
||||
You can simply extend debugger
|
||||
```js
|
||||
const log = require('debug')('auth');
|
||||
|
||||
//creates new debug instance with extended namespace
|
||||
const logSign = log.extend('sign');
|
||||
const logLogin = log.extend('login');
|
||||
|
||||
log('hello'); // auth hello
|
||||
logSign('hello'); //auth:sign hello
|
||||
logLogin('hello'); //auth:login hello
|
||||
```
|
||||
|
||||
## Set dynamically
|
||||
|
||||
You can also enable debug dynamically by calling the `enable()` method :
|
||||
|
||||
```js
|
||||
let debug = require('debug');
|
||||
|
||||
console.log(1, debug.enabled('test'));
|
||||
|
||||
debug.enable('test');
|
||||
console.log(2, debug.enabled('test'));
|
||||
|
||||
debug.disable();
|
||||
console.log(3, debug.enabled('test'));
|
||||
|
||||
```
|
||||
|
||||
print :
|
||||
```
|
||||
1 false
|
||||
2 true
|
||||
3 false
|
||||
```
|
||||
|
||||
Usage :
|
||||
`enable(namespaces)`
|
||||
`namespaces` can include modes separated by a colon and wildcards.
|
||||
|
||||
Note that calling `enable()` completely overrides previously set DEBUG variable :
|
||||
|
||||
```
|
||||
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
|
||||
=> false
|
||||
```
|
||||
|
||||
`disable()`
|
||||
|
||||
Will disable all namespaces. The functions returns the namespaces currently
|
||||
enabled (and skipped). This can be useful if you want to disable debugging
|
||||
temporarily without knowing what was enabled to begin with.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
let debug = require('debug');
|
||||
debug.enable('foo:*,-foo:bar');
|
||||
let namespaces = debug.disable();
|
||||
debug.enable(namespaces);
|
||||
```
|
||||
|
||||
Note: There is no guarantee that the string will be identical to the initial
|
||||
enable string, but semantically they will be identical.
|
||||
|
||||
## Checking whether a debug target is enabled
|
||||
|
||||
After you've created a debug instance, you can determine whether or not it is
|
||||
enabled by checking the `enabled` property:
|
||||
|
||||
```javascript
|
||||
const debug = require('debug')('http');
|
||||
|
||||
if (debug.enabled) {
|
||||
// do stuff...
|
||||
}
|
||||
```
|
||||
|
||||
You can also manually toggle this property to force the debug instance to be
|
||||
enabled or disabled.
|
||||
|
||||
## Usage in child processes
|
||||
|
||||
Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process.
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
worker = fork(WORKER_WRAP_PATH, [workerPath], {
|
||||
stdio: [
|
||||
/* stdin: */ 0,
|
||||
/* stdout: */ 'pipe',
|
||||
/* stderr: */ 'pipe',
|
||||
'ipc',
|
||||
],
|
||||
env: Object.assign({}, process.env, {
|
||||
DEBUG_COLORS: 1 // without this settings, colors won't be shown
|
||||
}),
|
||||
});
|
||||
|
||||
worker.stderr.pipe(process.stderr, { end: false });
|
||||
```
|
||||
|
||||
|
||||
## Authors
|
||||
|
||||
- TJ Holowaychuk
|
||||
- Nathan Rajlich
|
||||
- Andrew Rhyne
|
||||
- Josh Junon
|
||||
|
||||
## Backers
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
|
||||
|
||||
<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
|
||||
|
||||
|
||||
## Sponsors
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2018-2021 Josh Junon
|
||||
|
||||
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.
|
||||
59
WebUI/node_modules/mqtt/node_modules/debug/package.json
generated
vendored
Normal file
59
WebUI/node_modules/mqtt/node_modules/debug/package.json
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"name": "debug",
|
||||
"version": "4.3.4",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/debug-js/debug.git"
|
||||
},
|
||||
"description": "Lightweight debugging utility for Node.js and the browser",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"log",
|
||||
"debugger"
|
||||
],
|
||||
"files": [
|
||||
"src",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"author": "Josh Junon <josh.junon@protonmail.com>",
|
||||
"contributors": [
|
||||
"TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
|
||||
"Andrew Rhyne <rhyneandrew@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"lint": "xo",
|
||||
"test": "npm run test:node && npm run test:browser && npm run lint",
|
||||
"test:node": "istanbul cover _mocha -- test.js",
|
||||
"test:browser": "karma start --single-run",
|
||||
"test:coverage": "cat ./coverage/lcov.info | coveralls"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"brfs": "^2.0.1",
|
||||
"browserify": "^16.2.3",
|
||||
"coveralls": "^3.0.2",
|
||||
"istanbul": "^0.4.5",
|
||||
"karma": "^3.1.4",
|
||||
"karma-browserify": "^6.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-lcov-reporter": "^1.2.0",
|
||||
"xo": "^0.23.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"main": "./src/index.js",
|
||||
"browser": "./src/browser.js",
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
}
|
||||
269
WebUI/node_modules/mqtt/node_modules/debug/src/browser.js
generated
vendored
Normal file
269
WebUI/node_modules/mqtt/node_modules/debug/src/browser.js
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
/* eslint-env browser */
|
||||
|
||||
/**
|
||||
* This is the web browser implementation of `debug()`.
|
||||
*/
|
||||
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.storage = localstorage();
|
||||
exports.destroy = (() => {
|
||||
let warned = false;
|
||||
|
||||
return () => {
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [
|
||||
'#0000CC',
|
||||
'#0000FF',
|
||||
'#0033CC',
|
||||
'#0033FF',
|
||||
'#0066CC',
|
||||
'#0066FF',
|
||||
'#0099CC',
|
||||
'#0099FF',
|
||||
'#00CC00',
|
||||
'#00CC33',
|
||||
'#00CC66',
|
||||
'#00CC99',
|
||||
'#00CCCC',
|
||||
'#00CCFF',
|
||||
'#3300CC',
|
||||
'#3300FF',
|
||||
'#3333CC',
|
||||
'#3333FF',
|
||||
'#3366CC',
|
||||
'#3366FF',
|
||||
'#3399CC',
|
||||
'#3399FF',
|
||||
'#33CC00',
|
||||
'#33CC33',
|
||||
'#33CC66',
|
||||
'#33CC99',
|
||||
'#33CCCC',
|
||||
'#33CCFF',
|
||||
'#6600CC',
|
||||
'#6600FF',
|
||||
'#6633CC',
|
||||
'#6633FF',
|
||||
'#66CC00',
|
||||
'#66CC33',
|
||||
'#9900CC',
|
||||
'#9900FF',
|
||||
'#9933CC',
|
||||
'#9933FF',
|
||||
'#99CC00',
|
||||
'#99CC33',
|
||||
'#CC0000',
|
||||
'#CC0033',
|
||||
'#CC0066',
|
||||
'#CC0099',
|
||||
'#CC00CC',
|
||||
'#CC00FF',
|
||||
'#CC3300',
|
||||
'#CC3333',
|
||||
'#CC3366',
|
||||
'#CC3399',
|
||||
'#CC33CC',
|
||||
'#CC33FF',
|
||||
'#CC6600',
|
||||
'#CC6633',
|
||||
'#CC9900',
|
||||
'#CC9933',
|
||||
'#CCCC00',
|
||||
'#CCCC33',
|
||||
'#FF0000',
|
||||
'#FF0033',
|
||||
'#FF0066',
|
||||
'#FF0099',
|
||||
'#FF00CC',
|
||||
'#FF00FF',
|
||||
'#FF3300',
|
||||
'#FF3333',
|
||||
'#FF3366',
|
||||
'#FF3399',
|
||||
'#FF33CC',
|
||||
'#FF33FF',
|
||||
'#FF6600',
|
||||
'#FF6633',
|
||||
'#FF9900',
|
||||
'#FF9933',
|
||||
'#FFCC00',
|
||||
'#FFCC33'
|
||||
];
|
||||
|
||||
/**
|
||||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||||
* and the Firebug extension (any Firefox version) are known
|
||||
* to support "%c" CSS customizations.
|
||||
*
|
||||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
function useColors() {
|
||||
// NB: In an Electron preload script, document will be defined but not fully
|
||||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||||
// explicitly
|
||||
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Internet Explorer and Edge do not support colors.
|
||||
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
||||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
||||
// Is firebug? http://stackoverflow.com/a/398120/376773
|
||||
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
||||
// Is firefox >= v31?
|
||||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||||
// Double check webkit in userAgent just in case we are in a worker
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorize log arguments if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
args[0] = (this.useColors ? '%c' : '') +
|
||||
this.namespace +
|
||||
(this.useColors ? ' %c' : ' ') +
|
||||
args[0] +
|
||||
(this.useColors ? '%c ' : ' ') +
|
||||
'+' + module.exports.humanize(this.diff);
|
||||
|
||||
if (!this.useColors) {
|
||||
return;
|
||||
}
|
||||
|
||||
const c = 'color: ' + this.color;
|
||||
args.splice(1, 0, c, 'color: inherit');
|
||||
|
||||
// The final "%c" is somewhat tricky, because there could be other
|
||||
// arguments passed either before or after the %c, so we need to
|
||||
// figure out the correct index to insert the CSS into
|
||||
let index = 0;
|
||||
let lastC = 0;
|
||||
args[0].replace(/%[a-zA-Z%]/g, match => {
|
||||
if (match === '%%') {
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
if (match === '%c') {
|
||||
// We only are interested in the *last* %c
|
||||
// (the user may have provided their own)
|
||||
lastC = index;
|
||||
}
|
||||
});
|
||||
|
||||
args.splice(lastC, 0, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `console.debug()` when available.
|
||||
* No-op when `console.debug` is not a "function".
|
||||
* If `console.debug` is not available, falls back
|
||||
* to `console.log`.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
exports.log = console.debug || console.log || (() => {});
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
function save(namespaces) {
|
||||
try {
|
||||
if (namespaces) {
|
||||
exports.storage.setItem('debug', namespaces);
|
||||
} else {
|
||||
exports.storage.removeItem('debug');
|
||||
}
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
function load() {
|
||||
let r;
|
||||
try {
|
||||
r = exports.storage.getItem('debug');
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
|
||||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||||
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
||||
r = process.env.DEBUG;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Localstorage attempts to return the localstorage.
|
||||
*
|
||||
* This is necessary because safari throws
|
||||
* when a user disables cookies/localstorage
|
||||
* and you attempt to access it.
|
||||
*
|
||||
* @return {LocalStorage}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function localstorage() {
|
||||
try {
|
||||
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
||||
// The Browser also has localStorage in the global context.
|
||||
return localStorage;
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = require('./common')(exports);
|
||||
|
||||
const {formatters} = module.exports;
|
||||
|
||||
/**
|
||||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||||
*/
|
||||
|
||||
formatters.j = function (v) {
|
||||
try {
|
||||
return JSON.stringify(v);
|
||||
} catch (error) {
|
||||
return '[UnexpectedJSONParseError]: ' + error.message;
|
||||
}
|
||||
};
|
||||
274
WebUI/node_modules/mqtt/node_modules/debug/src/common.js
generated
vendored
Normal file
274
WebUI/node_modules/mqtt/node_modules/debug/src/common.js
generated
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
|
||||
/**
|
||||
* This is the common logic for both the Node.js and web browser
|
||||
* implementations of `debug()`.
|
||||
*/
|
||||
|
||||
function setup(env) {
|
||||
createDebug.debug = createDebug;
|
||||
createDebug.default = createDebug;
|
||||
createDebug.coerce = coerce;
|
||||
createDebug.disable = disable;
|
||||
createDebug.enable = enable;
|
||||
createDebug.enabled = enabled;
|
||||
createDebug.humanize = require('ms');
|
||||
createDebug.destroy = destroy;
|
||||
|
||||
Object.keys(env).forEach(key => {
|
||||
createDebug[key] = env[key];
|
||||
});
|
||||
|
||||
/**
|
||||
* The currently active debug mode names, and names to skip.
|
||||
*/
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
/**
|
||||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||||
*
|
||||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||||
*/
|
||||
createDebug.formatters = {};
|
||||
|
||||
/**
|
||||
* Selects a color for a debug namespace
|
||||
* @param {String} namespace The namespace string for the debug instance to be colored
|
||||
* @return {Number|String} An ANSI color code for the given namespace
|
||||
* @api private
|
||||
*/
|
||||
function selectColor(namespace) {
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < namespace.length; i++) {
|
||||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
||||
}
|
||||
createDebug.selectColor = selectColor;
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `namespace`.
|
||||
*
|
||||
* @param {String} namespace
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
function createDebug(namespace) {
|
||||
let prevTime;
|
||||
let enableOverride = null;
|
||||
let namespacesCache;
|
||||
let enabledCache;
|
||||
|
||||
function debug(...args) {
|
||||
// Disabled?
|
||||
if (!debug.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = debug;
|
||||
|
||||
// Set `diff` timestamp
|
||||
const curr = Number(new Date());
|
||||
const ms = curr - (prevTime || curr);
|
||||
self.diff = ms;
|
||||
self.prev = prevTime;
|
||||
self.curr = curr;
|
||||
prevTime = curr;
|
||||
|
||||
args[0] = createDebug.coerce(args[0]);
|
||||
|
||||
if (typeof args[0] !== 'string') {
|
||||
// Anything else let's inspect with %O
|
||||
args.unshift('%O');
|
||||
}
|
||||
|
||||
// Apply any `formatters` transformations
|
||||
let index = 0;
|
||||
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
||||
// If we encounter an escaped % then don't increase the array index
|
||||
if (match === '%%') {
|
||||
return '%';
|
||||
}
|
||||
index++;
|
||||
const formatter = createDebug.formatters[format];
|
||||
if (typeof formatter === 'function') {
|
||||
const val = args[index];
|
||||
match = formatter.call(self, val);
|
||||
|
||||
// Now we need to remove `args[index]` since it's inlined in the `format`
|
||||
args.splice(index, 1);
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
// Apply env-specific formatting (colors, etc.)
|
||||
createDebug.formatArgs.call(self, args);
|
||||
|
||||
const logFn = self.log || createDebug.log;
|
||||
logFn.apply(self, args);
|
||||
}
|
||||
|
||||
debug.namespace = namespace;
|
||||
debug.useColors = createDebug.useColors();
|
||||
debug.color = createDebug.selectColor(namespace);
|
||||
debug.extend = extend;
|
||||
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
||||
|
||||
Object.defineProperty(debug, 'enabled', {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: () => {
|
||||
if (enableOverride !== null) {
|
||||
return enableOverride;
|
||||
}
|
||||
if (namespacesCache !== createDebug.namespaces) {
|
||||
namespacesCache = createDebug.namespaces;
|
||||
enabledCache = createDebug.enabled(namespace);
|
||||
}
|
||||
|
||||
return enabledCache;
|
||||
},
|
||||
set: v => {
|
||||
enableOverride = v;
|
||||
}
|
||||
});
|
||||
|
||||
// Env-specific initialization logic for debug instances
|
||||
if (typeof createDebug.init === 'function') {
|
||||
createDebug.init(debug);
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
function extend(namespace, delimiter) {
|
||||
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
||||
newDebug.log = this.log;
|
||||
return newDebug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a debug mode by namespaces. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function enable(namespaces) {
|
||||
createDebug.save(namespaces);
|
||||
createDebug.namespaces = namespaces;
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
let i;
|
||||
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
||||
const len = split.length;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!split[i]) {
|
||||
// ignore empty strings
|
||||
continue;
|
||||
}
|
||||
|
||||
namespaces = split[i].replace(/\*/g, '.*?');
|
||||
|
||||
if (namespaces[0] === '-') {
|
||||
createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$'));
|
||||
} else {
|
||||
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @return {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function disable() {
|
||||
const namespaces = [
|
||||
...createDebug.names.map(toNamespace),
|
||||
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
||||
].join(',');
|
||||
createDebug.enable('');
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
function enabled(name) {
|
||||
if (name[name.length - 1] === '*') {
|
||||
return true;
|
||||
}
|
||||
|
||||
let i;
|
||||
let len;
|
||||
|
||||
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
||||
if (createDebug.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
||||
if (createDebug.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert regexp to namespace
|
||||
*
|
||||
* @param {RegExp} regxep
|
||||
* @return {String} namespace
|
||||
* @api private
|
||||
*/
|
||||
function toNamespace(regexp) {
|
||||
return regexp.toString()
|
||||
.substring(2, regexp.toString().length - 2)
|
||||
.replace(/\.\*\?$/, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerce `val`.
|
||||
*
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed}
|
||||
* @api private
|
||||
*/
|
||||
function coerce(val) {
|
||||
if (val instanceof Error) {
|
||||
return val.stack || val.message;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX DO NOT USE. This is a temporary stub function.
|
||||
* XXX It WILL be removed in the next major release.
|
||||
*/
|
||||
function destroy() {
|
||||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||
}
|
||||
|
||||
createDebug.enable(createDebug.load());
|
||||
|
||||
return createDebug;
|
||||
}
|
||||
|
||||
module.exports = setup;
|
||||
10
WebUI/node_modules/mqtt/node_modules/debug/src/index.js
generated
vendored
Normal file
10
WebUI/node_modules/mqtt/node_modules/debug/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Detect Electron renderer / nwjs process, which is node, but we should
|
||||
* treat as a browser.
|
||||
*/
|
||||
|
||||
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
|
||||
module.exports = require('./browser.js');
|
||||
} else {
|
||||
module.exports = require('./node.js');
|
||||
}
|
||||
263
WebUI/node_modules/mqtt/node_modules/debug/src/node.js
generated
vendored
Normal file
263
WebUI/node_modules/mqtt/node_modules/debug/src/node.js
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
const tty = require('tty');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* This is the Node.js implementation of `debug()`.
|
||||
*/
|
||||
|
||||
exports.init = init;
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.destroy = util.deprecate(
|
||||
() => {},
|
||||
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
|
||||
);
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||||
|
||||
try {
|
||||
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const supportsColor = require('supports-color');
|
||||
|
||||
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
||||
exports.colors = [
|
||||
20,
|
||||
21,
|
||||
26,
|
||||
27,
|
||||
32,
|
||||
33,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
56,
|
||||
57,
|
||||
62,
|
||||
63,
|
||||
68,
|
||||
69,
|
||||
74,
|
||||
75,
|
||||
76,
|
||||
77,
|
||||
78,
|
||||
79,
|
||||
80,
|
||||
81,
|
||||
92,
|
||||
93,
|
||||
98,
|
||||
99,
|
||||
112,
|
||||
113,
|
||||
128,
|
||||
129,
|
||||
134,
|
||||
135,
|
||||
148,
|
||||
149,
|
||||
160,
|
||||
161,
|
||||
162,
|
||||
163,
|
||||
164,
|
||||
165,
|
||||
166,
|
||||
167,
|
||||
168,
|
||||
169,
|
||||
170,
|
||||
171,
|
||||
172,
|
||||
173,
|
||||
178,
|
||||
179,
|
||||
184,
|
||||
185,
|
||||
196,
|
||||
197,
|
||||
198,
|
||||
199,
|
||||
200,
|
||||
201,
|
||||
202,
|
||||
203,
|
||||
204,
|
||||
205,
|
||||
206,
|
||||
207,
|
||||
208,
|
||||
209,
|
||||
214,
|
||||
215,
|
||||
220,
|
||||
221
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up the default `inspectOpts` object from the environment variables.
|
||||
*
|
||||
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
||||
*/
|
||||
|
||||
exports.inspectOpts = Object.keys(process.env).filter(key => {
|
||||
return /^debug_/i.test(key);
|
||||
}).reduce((obj, key) => {
|
||||
// Camel-case
|
||||
const prop = key
|
||||
.substring(6)
|
||||
.toLowerCase()
|
||||
.replace(/_([a-z])/g, (_, k) => {
|
||||
return k.toUpperCase();
|
||||
});
|
||||
|
||||
// Coerce string value into JS value
|
||||
let val = process.env[key];
|
||||
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
||||
val = true;
|
||||
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
||||
val = false;
|
||||
} else if (val === 'null') {
|
||||
val = null;
|
||||
} else {
|
||||
val = Number(val);
|
||||
}
|
||||
|
||||
obj[prop] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
return 'colors' in exports.inspectOpts ?
|
||||
Boolean(exports.inspectOpts.colors) :
|
||||
tty.isatty(process.stderr.fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ANSI color escape codes if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
const {namespace: name, useColors} = this;
|
||||
|
||||
if (useColors) {
|
||||
const c = this.color;
|
||||
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
||||
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
||||
|
||||
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
||||
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
|
||||
} else {
|
||||
args[0] = getDate() + name + ' ' + args[0];
|
||||
}
|
||||
}
|
||||
|
||||
function getDate() {
|
||||
if (exports.inspectOpts.hideDate) {
|
||||
return '';
|
||||
}
|
||||
return new Date().toISOString() + ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
||||
*/
|
||||
|
||||
function log(...args) {
|
||||
return process.stderr.write(util.format(...args) + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
function save(namespaces) {
|
||||
if (namespaces) {
|
||||
process.env.DEBUG = namespaces;
|
||||
} else {
|
||||
// If you set a process.env field to null or undefined, it gets cast to the
|
||||
// string 'null' or 'undefined'. Just delete instead.
|
||||
delete process.env.DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
return process.env.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init logic for `debug` instances.
|
||||
*
|
||||
* Create a new `inspectOpts` object in case `useColors` is set
|
||||
* differently for a particular `debug` instance.
|
||||
*/
|
||||
|
||||
function init(debug) {
|
||||
debug.inspectOpts = {};
|
||||
|
||||
const keys = Object.keys(exports.inspectOpts);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = require('./common')(exports);
|
||||
|
||||
const {formatters} = module.exports;
|
||||
|
||||
/**
|
||||
* Map %o to `util.inspect()`, all on a single line.
|
||||
*/
|
||||
|
||||
formatters.o = function (v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts)
|
||||
.split('\n')
|
||||
.map(str => str.trim())
|
||||
.join(' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Map %O to `util.inspect()`, allowing multiple lines if needed.
|
||||
*/
|
||||
|
||||
formatters.O = function (v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts);
|
||||
};
|
||||
162
WebUI/node_modules/mqtt/node_modules/ms/index.js
generated
vendored
Normal file
162
WebUI/node_modules/mqtt/node_modules/ms/index.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
var s = 1000;
|
||||
var m = s * 60;
|
||||
var h = m * 60;
|
||||
var d = h * 24;
|
||||
var w = d * 7;
|
||||
var y = d * 365.25;
|
||||
|
||||
/**
|
||||
* Parse or format the given `val`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `long` verbose formatting [false]
|
||||
*
|
||||
* @param {String|Number} val
|
||||
* @param {Object} [options]
|
||||
* @throws {Error} throw an error if val is not a non-empty string or a number
|
||||
* @return {String|Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports = function(val, options) {
|
||||
options = options || {};
|
||||
var type = typeof val;
|
||||
if (type === 'string' && val.length > 0) {
|
||||
return parse(val);
|
||||
} else if (type === 'number' && isFinite(val)) {
|
||||
return options.long ? fmtLong(val) : fmtShort(val);
|
||||
}
|
||||
throw new Error(
|
||||
'val is not a non-empty string or a valid number. val=' +
|
||||
JSON.stringify(val)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the given `str` and return milliseconds.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse(str) {
|
||||
str = String(str);
|
||||
if (str.length > 100) {
|
||||
return;
|
||||
}
|
||||
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
||||
str
|
||||
);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
var n = parseFloat(match[1]);
|
||||
var type = (match[2] || 'ms').toLowerCase();
|
||||
switch (type) {
|
||||
case 'years':
|
||||
case 'year':
|
||||
case 'yrs':
|
||||
case 'yr':
|
||||
case 'y':
|
||||
return n * y;
|
||||
case 'weeks':
|
||||
case 'week':
|
||||
case 'w':
|
||||
return n * w;
|
||||
case 'days':
|
||||
case 'day':
|
||||
case 'd':
|
||||
return n * d;
|
||||
case 'hours':
|
||||
case 'hour':
|
||||
case 'hrs':
|
||||
case 'hr':
|
||||
case 'h':
|
||||
return n * h;
|
||||
case 'minutes':
|
||||
case 'minute':
|
||||
case 'mins':
|
||||
case 'min':
|
||||
case 'm':
|
||||
return n * m;
|
||||
case 'seconds':
|
||||
case 'second':
|
||||
case 'secs':
|
||||
case 'sec':
|
||||
case 's':
|
||||
return n * s;
|
||||
case 'milliseconds':
|
||||
case 'millisecond':
|
||||
case 'msecs':
|
||||
case 'msec':
|
||||
case 'ms':
|
||||
return n;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Short format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtShort(ms) {
|
||||
var msAbs = Math.abs(ms);
|
||||
if (msAbs >= d) {
|
||||
return Math.round(ms / d) + 'd';
|
||||
}
|
||||
if (msAbs >= h) {
|
||||
return Math.round(ms / h) + 'h';
|
||||
}
|
||||
if (msAbs >= m) {
|
||||
return Math.round(ms / m) + 'm';
|
||||
}
|
||||
if (msAbs >= s) {
|
||||
return Math.round(ms / s) + 's';
|
||||
}
|
||||
return ms + 'ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Long format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtLong(ms) {
|
||||
var msAbs = Math.abs(ms);
|
||||
if (msAbs >= d) {
|
||||
return plural(ms, msAbs, d, 'day');
|
||||
}
|
||||
if (msAbs >= h) {
|
||||
return plural(ms, msAbs, h, 'hour');
|
||||
}
|
||||
if (msAbs >= m) {
|
||||
return plural(ms, msAbs, m, 'minute');
|
||||
}
|
||||
if (msAbs >= s) {
|
||||
return plural(ms, msAbs, s, 'second');
|
||||
}
|
||||
return ms + ' ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluralization helper.
|
||||
*/
|
||||
|
||||
function plural(ms, msAbs, n, name) {
|
||||
var isPlural = msAbs >= n * 1.5;
|
||||
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
||||
}
|
||||
21
WebUI/node_modules/mqtt/node_modules/ms/license.md
generated
vendored
Normal file
21
WebUI/node_modules/mqtt/node_modules/ms/license.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Zeit, Inc.
|
||||
|
||||
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.
|
||||
37
WebUI/node_modules/mqtt/node_modules/ms/package.json
generated
vendored
Normal file
37
WebUI/node_modules/mqtt/node_modules/ms/package.json
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "ms",
|
||||
"version": "2.1.2",
|
||||
"description": "Tiny millisecond conversion utility",
|
||||
"repository": "zeit/ms",
|
||||
"main": "./index",
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"lint": "eslint lib/* bin/*",
|
||||
"test": "mocha tests.js"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"npm run lint",
|
||||
"prettier --single-quote --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"eslint": "4.12.1",
|
||||
"expect.js": "0.3.1",
|
||||
"husky": "0.14.3",
|
||||
"lint-staged": "5.0.0",
|
||||
"mocha": "4.0.1"
|
||||
}
|
||||
}
|
||||
60
WebUI/node_modules/mqtt/node_modules/ms/readme.md
generated
vendored
Normal file
60
WebUI/node_modules/mqtt/node_modules/ms/readme.md
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
# ms
|
||||
|
||||
[](https://travis-ci.org/zeit/ms)
|
||||
[](https://spectrum.chat/zeit)
|
||||
|
||||
Use this package to easily convert various time formats to milliseconds.
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
ms('2 days') // 172800000
|
||||
ms('1d') // 86400000
|
||||
ms('10h') // 36000000
|
||||
ms('2.5 hrs') // 9000000
|
||||
ms('2h') // 7200000
|
||||
ms('1m') // 60000
|
||||
ms('5s') // 5000
|
||||
ms('1y') // 31557600000
|
||||
ms('100') // 100
|
||||
ms('-3 days') // -259200000
|
||||
ms('-1h') // -3600000
|
||||
ms('-200') // -200
|
||||
```
|
||||
|
||||
### Convert from Milliseconds
|
||||
|
||||
```js
|
||||
ms(60000) // "1m"
|
||||
ms(2 * 60000) // "2m"
|
||||
ms(-3 * 60000) // "-3m"
|
||||
ms(ms('10 hours')) // "10h"
|
||||
```
|
||||
|
||||
### Time Format Written-Out
|
||||
|
||||
```js
|
||||
ms(60000, { long: true }) // "1 minute"
|
||||
ms(2 * 60000, { long: true }) // "2 minutes"
|
||||
ms(-3 * 60000, { long: true }) // "-3 minutes"
|
||||
ms(ms('10 hours'), { long: true }) // "10 hours"
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Works both in [Node.js](https://nodejs.org) and in the browser
|
||||
- If a number is supplied to `ms`, a string with a unit is returned
|
||||
- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`)
|
||||
- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned
|
||||
|
||||
## Related Packages
|
||||
|
||||
- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time.
|
||||
|
||||
## Caught a Bug?
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
|
||||
2. Link the package to the global module directory: `npm link`
|
||||
3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms!
|
||||
|
||||
As always, you can run the tests using: `npm test`
|
||||
21
WebUI/node_modules/mqtt/node_modules/ws/LICENSE
generated
vendored
Normal file
21
WebUI/node_modules/mqtt/node_modules/ws/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
||||
|
||||
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.
|
||||
495
WebUI/node_modules/mqtt/node_modules/ws/README.md
generated
vendored
Normal file
495
WebUI/node_modules/mqtt/node_modules/ws/README.md
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
||||
# ws: a Node.js WebSocket library
|
||||
|
||||
[](https://www.npmjs.com/package/ws)
|
||||
[](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster)
|
||||
[](https://coveralls.io/github/websockets/ws)
|
||||
|
||||
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
|
||||
server implementation.
|
||||
|
||||
Passes the quite extensive Autobahn test suite: [server][server-report],
|
||||
[client][client-report].
|
||||
|
||||
**Note**: This module does not work in the browser. The client in the docs is a
|
||||
reference to a back end with the role of a client in the WebSocket
|
||||
communication. Browser clients must use the native
|
||||
[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
||||
object. To make the same code work seamlessly on Node.js and the browser, you
|
||||
can use one of the many wrappers available on npm, like
|
||||
[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Protocol support](#protocol-support)
|
||||
- [Installing](#installing)
|
||||
- [Opt-in for performance](#opt-in-for-performance)
|
||||
- [API docs](#api-docs)
|
||||
- [WebSocket compression](#websocket-compression)
|
||||
- [Usage examples](#usage-examples)
|
||||
- [Sending and receiving text data](#sending-and-receiving-text-data)
|
||||
- [Sending binary data](#sending-binary-data)
|
||||
- [Simple server](#simple-server)
|
||||
- [External HTTP/S server](#external-https-server)
|
||||
- [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
|
||||
- [Client authentication](#client-authentication)
|
||||
- [Server broadcast](#server-broadcast)
|
||||
- [echo.websocket.org demo](#echowebsocketorg-demo)
|
||||
- [Use the Node.js streams API](#use-the-nodejs-streams-api)
|
||||
- [Other examples](#other-examples)
|
||||
- [FAQ](#faq)
|
||||
- [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
|
||||
- [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
|
||||
- [How to connect via a proxy?](#how-to-connect-via-a-proxy)
|
||||
- [Changelog](#changelog)
|
||||
- [License](#license)
|
||||
|
||||
## Protocol support
|
||||
|
||||
- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
|
||||
- **HyBi drafts 13-17** (Current default, alternatively option
|
||||
`protocolVersion: 13`)
|
||||
|
||||
## Installing
|
||||
|
||||
```
|
||||
npm install ws
|
||||
```
|
||||
|
||||
### Opt-in for performance
|
||||
|
||||
There are 2 optional modules that can be installed along side with the ws
|
||||
module. These modules are binary addons which improve certain operations.
|
||||
Prebuilt binaries are available for the most popular platforms so you don't
|
||||
necessarily need to have a C++ compiler installed on your machine.
|
||||
|
||||
- `npm install --save-optional bufferutil`: Allows to efficiently perform
|
||||
operations such as masking and unmasking the data payload of the WebSocket
|
||||
frames.
|
||||
- `npm install --save-optional utf-8-validate`: Allows to efficiently check if a
|
||||
message contains valid UTF-8.
|
||||
|
||||
## API docs
|
||||
|
||||
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
|
||||
utility functions.
|
||||
|
||||
## WebSocket compression
|
||||
|
||||
ws supports the [permessage-deflate extension][permessage-deflate] which enables
|
||||
the client and server to negotiate a compression algorithm and its parameters,
|
||||
and then selectively apply it to the data payloads of each WebSocket message.
|
||||
|
||||
The extension is disabled by default on the server and enabled by default on the
|
||||
client. It adds a significant overhead in terms of performance and memory
|
||||
consumption so we suggest to enable it only if it is really needed.
|
||||
|
||||
Note that Node.js has a variety of issues with high-performance compression,
|
||||
where increased concurrency, especially on Linux, can lead to [catastrophic
|
||||
memory fragmentation][node-zlib-bug] and slow performance. If you intend to use
|
||||
permessage-deflate in production, it is worthwhile to set up a test
|
||||
representative of your workload and ensure Node.js/zlib will handle it with
|
||||
acceptable performance and memory usage.
|
||||
|
||||
Tuning of permessage-deflate can be done via the options defined below. You can
|
||||
also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly
|
||||
into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
|
||||
|
||||
See [the docs][ws-server-options] for more options.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const wss = new WebSocket.Server({
|
||||
port: 8080,
|
||||
perMessageDeflate: {
|
||||
zlibDeflateOptions: {
|
||||
// See zlib defaults.
|
||||
chunkSize: 1024,
|
||||
memLevel: 7,
|
||||
level: 3
|
||||
},
|
||||
zlibInflateOptions: {
|
||||
chunkSize: 10 * 1024
|
||||
},
|
||||
// Other options settable:
|
||||
clientNoContextTakeover: true, // Defaults to negotiated value.
|
||||
serverNoContextTakeover: true, // Defaults to negotiated value.
|
||||
serverMaxWindowBits: 10, // Defaults to negotiated value.
|
||||
// Below options specified as default values.
|
||||
concurrencyLimit: 10, // Limits zlib concurrency for perf.
|
||||
threshold: 1024 // Size (in bytes) below which messages
|
||||
// should not be compressed.
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The client will only use the extension if it is supported and enabled on the
|
||||
server. To always disable the extension on the client set the
|
||||
`perMessageDeflate` option to `false`.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('ws://www.host.com/path', {
|
||||
perMessageDeflate: false
|
||||
});
|
||||
```
|
||||
|
||||
## Usage examples
|
||||
|
||||
### Sending and receiving text data
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('ws://www.host.com/path');
|
||||
|
||||
ws.on('open', function open() {
|
||||
ws.send('something');
|
||||
});
|
||||
|
||||
ws.on('message', function incoming(data) {
|
||||
console.log(data);
|
||||
});
|
||||
```
|
||||
|
||||
### Sending binary data
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('ws://www.host.com/path');
|
||||
|
||||
ws.on('open', function open() {
|
||||
const array = new Float32Array(5);
|
||||
|
||||
for (var i = 0; i < array.length; ++i) {
|
||||
array[i] = i / 2;
|
||||
}
|
||||
|
||||
ws.send(array);
|
||||
});
|
||||
```
|
||||
|
||||
### Simple server
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(message) {
|
||||
console.log('received: %s', message);
|
||||
});
|
||||
|
||||
ws.send('something');
|
||||
});
|
||||
```
|
||||
|
||||
### External HTTP/S server
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const server = https.createServer({
|
||||
cert: fs.readFileSync('/path/to/cert.pem'),
|
||||
key: fs.readFileSync('/path/to/key.pem')
|
||||
});
|
||||
const wss = new WebSocket.Server({ server });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(message) {
|
||||
console.log('received: %s', message);
|
||||
});
|
||||
|
||||
ws.send('something');
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
```
|
||||
|
||||
### Multiple servers sharing a single HTTP/S server
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const WebSocket = require('ws');
|
||||
const url = require('url');
|
||||
|
||||
const server = http.createServer();
|
||||
const wss1 = new WebSocket.Server({ noServer: true });
|
||||
const wss2 = new WebSocket.Server({ noServer: true });
|
||||
|
||||
wss1.on('connection', function connection(ws) {
|
||||
// ...
|
||||
});
|
||||
|
||||
wss2.on('connection', function connection(ws) {
|
||||
// ...
|
||||
});
|
||||
|
||||
server.on('upgrade', function upgrade(request, socket, head) {
|
||||
const pathname = url.parse(request.url).pathname;
|
||||
|
||||
if (pathname === '/foo') {
|
||||
wss1.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wss1.emit('connection', ws, request);
|
||||
});
|
||||
} else if (pathname === '/bar') {
|
||||
wss2.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wss2.emit('connection', ws, request);
|
||||
});
|
||||
} else {
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
```
|
||||
|
||||
### Client authentication
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const server = http.createServer();
|
||||
const wss = new WebSocket.Server({ noServer: true });
|
||||
|
||||
wss.on('connection', function connection(ws, request, client) {
|
||||
ws.on('message', function message(msg) {
|
||||
console.log(`Received message ${msg} from user ${client}`);
|
||||
});
|
||||
});
|
||||
|
||||
server.on('upgrade', function upgrade(request, socket, head) {
|
||||
// This function is not defined on purpose. Implement it with your own logic.
|
||||
authenticate(request, (err, client) => {
|
||||
if (err || !client) {
|
||||
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
wss.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wss.emit('connection', ws, request, client);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
```
|
||||
|
||||
Also see the provided [example][session-parse-example] using `express-session`.
|
||||
|
||||
### Server broadcast
|
||||
|
||||
A client WebSocket broadcasting to all connected WebSocket clients, including
|
||||
itself.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(data) {
|
||||
wss.clients.forEach(function each(client) {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
A client WebSocket broadcasting to every other connected WebSocket clients,
|
||||
excluding itself.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(data) {
|
||||
wss.clients.forEach(function each(client) {
|
||||
if (client !== ws && client.readyState === WebSocket.OPEN) {
|
||||
client.send(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### echo.websocket.org demo
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('wss://echo.websocket.org/', {
|
||||
origin: 'https://websocket.org'
|
||||
});
|
||||
|
||||
ws.on('open', function open() {
|
||||
console.log('connected');
|
||||
ws.send(Date.now());
|
||||
});
|
||||
|
||||
ws.on('close', function close() {
|
||||
console.log('disconnected');
|
||||
});
|
||||
|
||||
ws.on('message', function incoming(data) {
|
||||
console.log(`Roundtrip time: ${Date.now() - data} ms`);
|
||||
|
||||
setTimeout(function timeout() {
|
||||
ws.send(Date.now());
|
||||
}, 500);
|
||||
});
|
||||
```
|
||||
|
||||
### Use the Node.js streams API
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('wss://echo.websocket.org/', {
|
||||
origin: 'https://websocket.org'
|
||||
});
|
||||
|
||||
const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' });
|
||||
|
||||
duplex.pipe(process.stdout);
|
||||
process.stdin.pipe(duplex);
|
||||
```
|
||||
|
||||
### Other examples
|
||||
|
||||
For a full example with a browser client communicating with a ws server, see the
|
||||
examples folder.
|
||||
|
||||
Otherwise, see the test cases.
|
||||
|
||||
## FAQ
|
||||
|
||||
### How to get the IP address of the client?
|
||||
|
||||
The remote IP address can be obtained from the raw socket.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws, req) {
|
||||
const ip = req.socket.remoteAddress;
|
||||
});
|
||||
```
|
||||
|
||||
When the server runs behind a proxy like NGINX, the de-facto standard is to use
|
||||
the `X-Forwarded-For` header.
|
||||
|
||||
```js
|
||||
wss.on('connection', function connection(ws, req) {
|
||||
const ip = req.headers['x-forwarded-for'].split(',')[0].trim();
|
||||
});
|
||||
```
|
||||
|
||||
### How to detect and close broken connections?
|
||||
|
||||
Sometimes the link between the server and the client can be interrupted in a way
|
||||
that keeps both the server and the client unaware of the broken state of the
|
||||
connection (e.g. when pulling the cord).
|
||||
|
||||
In these cases ping messages can be used as a means to verify that the remote
|
||||
endpoint is still responsive.
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
function noop() {}
|
||||
|
||||
function heartbeat() {
|
||||
this.isAlive = true;
|
||||
}
|
||||
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.isAlive = true;
|
||||
ws.on('pong', heartbeat);
|
||||
});
|
||||
|
||||
const interval = setInterval(function ping() {
|
||||
wss.clients.forEach(function each(ws) {
|
||||
if (ws.isAlive === false) return ws.terminate();
|
||||
|
||||
ws.isAlive = false;
|
||||
ws.ping(noop);
|
||||
});
|
||||
}, 30000);
|
||||
|
||||
wss.on('close', function close() {
|
||||
clearInterval(interval);
|
||||
});
|
||||
```
|
||||
|
||||
Pong messages are automatically sent in response to ping messages as required by
|
||||
the spec.
|
||||
|
||||
Just like the server example above your clients might as well lose connection
|
||||
without knowing it. You might want to add a ping listener on your clients to
|
||||
prevent that. A simple implementation would be:
|
||||
|
||||
```js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
function heartbeat() {
|
||||
clearTimeout(this.pingTimeout);
|
||||
|
||||
// Use `WebSocket#terminate()`, which immediately destroys the connection,
|
||||
// instead of `WebSocket#close()`, which waits for the close timer.
|
||||
// Delay should be equal to the interval at which your server
|
||||
// sends out pings plus a conservative assumption of the latency.
|
||||
this.pingTimeout = setTimeout(() => {
|
||||
this.terminate();
|
||||
}, 30000 + 1000);
|
||||
}
|
||||
|
||||
const client = new WebSocket('wss://echo.websocket.org/');
|
||||
|
||||
client.on('open', heartbeat);
|
||||
client.on('ping', heartbeat);
|
||||
client.on('close', function clear() {
|
||||
clearTimeout(this.pingTimeout);
|
||||
});
|
||||
```
|
||||
|
||||
### How to connect via a proxy?
|
||||
|
||||
Use a custom `http.Agent` implementation like [https-proxy-agent][] or
|
||||
[socks-proxy-agent][].
|
||||
|
||||
## Changelog
|
||||
|
||||
We're using the GitHub [releases][changelog] for changelog entries.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[changelog]: https://github.com/websockets/ws/releases
|
||||
[client-report]: http://websockets.github.io/ws/autobahn/clients/
|
||||
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
|
||||
[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
|
||||
[node-zlib-deflaterawdocs]:
|
||||
https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
|
||||
[permessage-deflate]: https://tools.ietf.org/html/rfc7692
|
||||
[server-report]: http://websockets.github.io/ws/autobahn/servers/
|
||||
[session-parse-example]: ./examples/express-session-parse
|
||||
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
|
||||
[ws-server-options]:
|
||||
https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback
|
||||
8
WebUI/node_modules/mqtt/node_modules/ws/browser.js
generated
vendored
Normal file
8
WebUI/node_modules/mqtt/node_modules/ws/browser.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function () {
|
||||
throw new Error(
|
||||
'ws does not work in the browser. Browser clients must use the native ' +
|
||||
'WebSocket object'
|
||||
);
|
||||
};
|
||||
10
WebUI/node_modules/mqtt/node_modules/ws/index.js
generated
vendored
Normal file
10
WebUI/node_modules/mqtt/node_modules/ws/index.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const WebSocket = require('./lib/websocket');
|
||||
|
||||
WebSocket.createWebSocketStream = require('./lib/stream');
|
||||
WebSocket.Server = require('./lib/websocket-server');
|
||||
WebSocket.Receiver = require('./lib/receiver');
|
||||
WebSocket.Sender = require('./lib/sender');
|
||||
|
||||
module.exports = WebSocket;
|
||||
129
WebUI/node_modules/mqtt/node_modules/ws/lib/buffer-util.js
generated
vendored
Normal file
129
WebUI/node_modules/mqtt/node_modules/ws/lib/buffer-util.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
'use strict';
|
||||
|
||||
const { EMPTY_BUFFER } = require('./constants');
|
||||
|
||||
/**
|
||||
* Merges an array of buffers into a new buffer.
|
||||
*
|
||||
* @param {Buffer[]} list The array of buffers to concat
|
||||
* @param {Number} totalLength The total length of buffers in the list
|
||||
* @return {Buffer} The resulting buffer
|
||||
* @public
|
||||
*/
|
||||
function concat(list, totalLength) {
|
||||
if (list.length === 0) return EMPTY_BUFFER;
|
||||
if (list.length === 1) return list[0];
|
||||
|
||||
const target = Buffer.allocUnsafe(totalLength);
|
||||
let offset = 0;
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const buf = list[i];
|
||||
target.set(buf, offset);
|
||||
offset += buf.length;
|
||||
}
|
||||
|
||||
if (offset < totalLength) return target.slice(0, offset);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks a buffer using the given mask.
|
||||
*
|
||||
* @param {Buffer} source The buffer to mask
|
||||
* @param {Buffer} mask The mask to use
|
||||
* @param {Buffer} output The buffer where to store the result
|
||||
* @param {Number} offset The offset at which to start writing
|
||||
* @param {Number} length The number of bytes to mask.
|
||||
* @public
|
||||
*/
|
||||
function _mask(source, mask, output, offset, length) {
|
||||
for (let i = 0; i < length; i++) {
|
||||
output[offset + i] = source[i] ^ mask[i & 3];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmasks a buffer using the given mask.
|
||||
*
|
||||
* @param {Buffer} buffer The buffer to unmask
|
||||
* @param {Buffer} mask The mask to use
|
||||
* @public
|
||||
*/
|
||||
function _unmask(buffer, mask) {
|
||||
// Required until https://github.com/nodejs/node/issues/9006 is resolved.
|
||||
const length = buffer.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
buffer[i] ^= mask[i & 3];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a buffer to an `ArrayBuffer`.
|
||||
*
|
||||
* @param {Buffer} buf The buffer to convert
|
||||
* @return {ArrayBuffer} Converted buffer
|
||||
* @public
|
||||
*/
|
||||
function toArrayBuffer(buf) {
|
||||
if (buf.byteLength === buf.buffer.byteLength) {
|
||||
return buf.buffer;
|
||||
}
|
||||
|
||||
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `data` to a `Buffer`.
|
||||
*
|
||||
* @param {*} data The data to convert
|
||||
* @return {Buffer} The buffer
|
||||
* @throws {TypeError}
|
||||
* @public
|
||||
*/
|
||||
function toBuffer(data) {
|
||||
toBuffer.readOnly = true;
|
||||
|
||||
if (Buffer.isBuffer(data)) return data;
|
||||
|
||||
let buf;
|
||||
|
||||
if (data instanceof ArrayBuffer) {
|
||||
buf = Buffer.from(data);
|
||||
} else if (ArrayBuffer.isView(data)) {
|
||||
buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
||||
} else {
|
||||
buf = Buffer.from(data);
|
||||
toBuffer.readOnly = false;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
try {
|
||||
const bufferUtil = require('bufferutil');
|
||||
const bu = bufferUtil.BufferUtil || bufferUtil;
|
||||
|
||||
module.exports = {
|
||||
concat,
|
||||
mask(source, mask, output, offset, length) {
|
||||
if (length < 48) _mask(source, mask, output, offset, length);
|
||||
else bu.mask(source, mask, output, offset, length);
|
||||
},
|
||||
toArrayBuffer,
|
||||
toBuffer,
|
||||
unmask(buffer, mask) {
|
||||
if (buffer.length < 32) _unmask(buffer, mask);
|
||||
else bu.unmask(buffer, mask);
|
||||
}
|
||||
};
|
||||
} catch (e) /* istanbul ignore next */ {
|
||||
module.exports = {
|
||||
concat,
|
||||
mask: _mask,
|
||||
toArrayBuffer,
|
||||
toBuffer,
|
||||
unmask: _unmask
|
||||
};
|
||||
}
|
||||
10
WebUI/node_modules/mqtt/node_modules/ws/lib/constants.js
generated
vendored
Normal file
10
WebUI/node_modules/mqtt/node_modules/ws/lib/constants.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'],
|
||||
GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
|
||||
kStatusCode: Symbol('status-code'),
|
||||
kWebSocket: Symbol('websocket'),
|
||||
EMPTY_BUFFER: Buffer.alloc(0),
|
||||
NOOP: () => {}
|
||||
};
|
||||
184
WebUI/node_modules/mqtt/node_modules/ws/lib/event-target.js
generated
vendored
Normal file
184
WebUI/node_modules/mqtt/node_modules/ws/lib/event-target.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Class representing an event.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
class Event {
|
||||
/**
|
||||
* Create a new `Event`.
|
||||
*
|
||||
* @param {String} type The name of the event
|
||||
* @param {Object} target A reference to the target to which the event was
|
||||
* dispatched
|
||||
*/
|
||||
constructor(type, target) {
|
||||
this.target = target;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a message event.
|
||||
*
|
||||
* @extends Event
|
||||
* @private
|
||||
*/
|
||||
class MessageEvent extends Event {
|
||||
/**
|
||||
* Create a new `MessageEvent`.
|
||||
*
|
||||
* @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data
|
||||
* @param {WebSocket} target A reference to the target to which the event was
|
||||
* dispatched
|
||||
*/
|
||||
constructor(data, target) {
|
||||
super('message', target);
|
||||
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a close event.
|
||||
*
|
||||
* @extends Event
|
||||
* @private
|
||||
*/
|
||||
class CloseEvent extends Event {
|
||||
/**
|
||||
* Create a new `CloseEvent`.
|
||||
*
|
||||
* @param {Number} code The status code explaining why the connection is being
|
||||
* closed
|
||||
* @param {String} reason A human-readable string explaining why the
|
||||
* connection is closing
|
||||
* @param {WebSocket} target A reference to the target to which the event was
|
||||
* dispatched
|
||||
*/
|
||||
constructor(code, reason, target) {
|
||||
super('close', target);
|
||||
|
||||
this.wasClean = target._closeFrameReceived && target._closeFrameSent;
|
||||
this.reason = reason;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing an open event.
|
||||
*
|
||||
* @extends Event
|
||||
* @private
|
||||
*/
|
||||
class OpenEvent extends Event {
|
||||
/**
|
||||
* Create a new `OpenEvent`.
|
||||
*
|
||||
* @param {WebSocket} target A reference to the target to which the event was
|
||||
* dispatched
|
||||
*/
|
||||
constructor(target) {
|
||||
super('open', target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing an error event.
|
||||
*
|
||||
* @extends Event
|
||||
* @private
|
||||
*/
|
||||
class ErrorEvent extends Event {
|
||||
/**
|
||||
* Create a new `ErrorEvent`.
|
||||
*
|
||||
* @param {Object} error The error that generated this event
|
||||
* @param {WebSocket} target A reference to the target to which the event was
|
||||
* dispatched
|
||||
*/
|
||||
constructor(error, target) {
|
||||
super('error', target);
|
||||
|
||||
this.message = error.message;
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This provides methods for emulating the `EventTarget` interface. It's not
|
||||
* meant to be used directly.
|
||||
*
|
||||
* @mixin
|
||||
*/
|
||||
const EventTarget = {
|
||||
/**
|
||||
* Register an event listener.
|
||||
*
|
||||
* @param {String} type A string representing the event type to listen for
|
||||
* @param {Function} listener The listener to add
|
||||
* @param {Object} [options] An options object specifies characteristics about
|
||||
* the event listener
|
||||
* @param {Boolean} [options.once=false] A `Boolean`` indicating that the
|
||||
* listener should be invoked at most once after being added. If `true`,
|
||||
* the listener would be automatically removed when invoked.
|
||||
* @public
|
||||
*/
|
||||
addEventListener(type, listener, options) {
|
||||
if (typeof listener !== 'function') return;
|
||||
|
||||
function onMessage(data) {
|
||||
listener.call(this, new MessageEvent(data, this));
|
||||
}
|
||||
|
||||
function onClose(code, message) {
|
||||
listener.call(this, new CloseEvent(code, message, this));
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
listener.call(this, new ErrorEvent(error, this));
|
||||
}
|
||||
|
||||
function onOpen() {
|
||||
listener.call(this, new OpenEvent(this));
|
||||
}
|
||||
|
||||
const method = options && options.once ? 'once' : 'on';
|
||||
|
||||
if (type === 'message') {
|
||||
onMessage._listener = listener;
|
||||
this[method](type, onMessage);
|
||||
} else if (type === 'close') {
|
||||
onClose._listener = listener;
|
||||
this[method](type, onClose);
|
||||
} else if (type === 'error') {
|
||||
onError._listener = listener;
|
||||
this[method](type, onError);
|
||||
} else if (type === 'open') {
|
||||
onOpen._listener = listener;
|
||||
this[method](type, onOpen);
|
||||
} else {
|
||||
this[method](type, listener);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an event listener.
|
||||
*
|
||||
* @param {String} type A string representing the event type to remove
|
||||
* @param {Function} listener The listener to remove
|
||||
* @public
|
||||
*/
|
||||
removeEventListener(type, listener) {
|
||||
const listeners = this.listeners(type);
|
||||
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
if (listeners[i] === listener || listeners[i]._listener === listener) {
|
||||
this.removeListener(type, listeners[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = EventTarget;
|
||||
223
WebUI/node_modules/mqtt/node_modules/ws/lib/extension.js
generated
vendored
Normal file
223
WebUI/node_modules/mqtt/node_modules/ws/lib/extension.js
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
'use strict';
|
||||
|
||||
//
|
||||
// Allowed token characters:
|
||||
//
|
||||
// '!', '#', '$', '%', '&', ''', '*', '+', '-',
|
||||
// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
|
||||
//
|
||||
// tokenChars[32] === 0 // ' '
|
||||
// tokenChars[33] === 1 // '!'
|
||||
// tokenChars[34] === 0 // '"'
|
||||
// ...
|
||||
//
|
||||
// prettier-ignore
|
||||
const tokenChars = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
|
||||
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
|
||||
];
|
||||
|
||||
/**
|
||||
* Adds an offer to the map of extension offers or a parameter to the map of
|
||||
* parameters.
|
||||
*
|
||||
* @param {Object} dest The map of extension offers or parameters
|
||||
* @param {String} name The extension or parameter name
|
||||
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
||||
* parameter value
|
||||
* @private
|
||||
*/
|
||||
function push(dest, name, elem) {
|
||||
if (dest[name] === undefined) dest[name] = [elem];
|
||||
else dest[name].push(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
||||
*
|
||||
* @param {String} header The field value of the header
|
||||
* @return {Object} The parsed object
|
||||
* @public
|
||||
*/
|
||||
function parse(header) {
|
||||
const offers = Object.create(null);
|
||||
|
||||
if (header === undefined || header === '') return offers;
|
||||
|
||||
let params = Object.create(null);
|
||||
let mustUnescape = false;
|
||||
let isEscaping = false;
|
||||
let inQuotes = false;
|
||||
let extensionName;
|
||||
let paramName;
|
||||
let start = -1;
|
||||
let end = -1;
|
||||
let i = 0;
|
||||
|
||||
for (; i < header.length; i++) {
|
||||
const code = header.charCodeAt(i);
|
||||
|
||||
if (extensionName === undefined) {
|
||||
if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x20 /* ' ' */ || code === 0x09 /* '\t' */) {
|
||||
if (end === -1 && start !== -1) end = i;
|
||||
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
const name = header.slice(start, end);
|
||||
if (code === 0x2c) {
|
||||
push(offers, name, params);
|
||||
params = Object.create(null);
|
||||
} else {
|
||||
extensionName = name;
|
||||
}
|
||||
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else if (paramName === undefined) {
|
||||
if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x20 || code === 0x09) {
|
||||
if (end === -1 && start !== -1) end = i;
|
||||
} else if (code === 0x3b || code === 0x2c) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
push(params, header.slice(start, end), true);
|
||||
if (code === 0x2c) {
|
||||
push(offers, extensionName, params);
|
||||
params = Object.create(null);
|
||||
extensionName = undefined;
|
||||
}
|
||||
|
||||
start = end = -1;
|
||||
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
||||
paramName = header.slice(start, i);
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The value of a quoted-string after unescaping must conform to the
|
||||
// token ABNF, so only token characters are valid.
|
||||
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
||||
//
|
||||
if (isEscaping) {
|
||||
if (tokenChars[code] !== 1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
if (start === -1) start = i;
|
||||
else if (!mustUnescape) mustUnescape = true;
|
||||
isEscaping = false;
|
||||
} else if (inQuotes) {
|
||||
if (tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
||||
inQuotes = false;
|
||||
end = i;
|
||||
} else if (code === 0x5c /* '\' */) {
|
||||
isEscaping = true;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
||||
inQuotes = true;
|
||||
} else if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
||||
if (end === -1) end = i;
|
||||
} else if (code === 0x3b || code === 0x2c) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
let value = header.slice(start, end);
|
||||
if (mustUnescape) {
|
||||
value = value.replace(/\\/g, '');
|
||||
mustUnescape = false;
|
||||
}
|
||||
push(params, paramName, value);
|
||||
if (code === 0x2c) {
|
||||
push(offers, extensionName, params);
|
||||
params = Object.create(null);
|
||||
extensionName = undefined;
|
||||
}
|
||||
|
||||
paramName = undefined;
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start === -1 || inQuotes) {
|
||||
throw new SyntaxError('Unexpected end of input');
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
const token = header.slice(start, end);
|
||||
if (extensionName === undefined) {
|
||||
push(offers, token, params);
|
||||
} else {
|
||||
if (paramName === undefined) {
|
||||
push(params, token, true);
|
||||
} else if (mustUnescape) {
|
||||
push(params, paramName, token.replace(/\\/g, ''));
|
||||
} else {
|
||||
push(params, paramName, token);
|
||||
}
|
||||
push(offers, extensionName, params);
|
||||
}
|
||||
|
||||
return offers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the `Sec-WebSocket-Extensions` header field value.
|
||||
*
|
||||
* @param {Object} extensions The map of extensions and parameters to format
|
||||
* @return {String} A string representing the given object
|
||||
* @public
|
||||
*/
|
||||
function format(extensions) {
|
||||
return Object.keys(extensions)
|
||||
.map((extension) => {
|
||||
let configurations = extensions[extension];
|
||||
if (!Array.isArray(configurations)) configurations = [configurations];
|
||||
return configurations
|
||||
.map((params) => {
|
||||
return [extension]
|
||||
.concat(
|
||||
Object.keys(params).map((k) => {
|
||||
let values = params[k];
|
||||
if (!Array.isArray(values)) values = [values];
|
||||
return values
|
||||
.map((v) => (v === true ? k : `${k}=${v}`))
|
||||
.join('; ');
|
||||
})
|
||||
)
|
||||
.join('; ');
|
||||
})
|
||||
.join(', ');
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
module.exports = { format, parse };
|
||||
55
WebUI/node_modules/mqtt/node_modules/ws/lib/limiter.js
generated
vendored
Normal file
55
WebUI/node_modules/mqtt/node_modules/ws/lib/limiter.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const kDone = Symbol('kDone');
|
||||
const kRun = Symbol('kRun');
|
||||
|
||||
/**
|
||||
* A very simple job queue with adjustable concurrency. Adapted from
|
||||
* https://github.com/STRML/async-limiter
|
||||
*/
|
||||
class Limiter {
|
||||
/**
|
||||
* Creates a new `Limiter`.
|
||||
*
|
||||
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
|
||||
* to run concurrently
|
||||
*/
|
||||
constructor(concurrency) {
|
||||
this[kDone] = () => {
|
||||
this.pending--;
|
||||
this[kRun]();
|
||||
};
|
||||
this.concurrency = concurrency || Infinity;
|
||||
this.jobs = [];
|
||||
this.pending = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a job to the queue.
|
||||
*
|
||||
* @param {Function} job The job to run
|
||||
* @public
|
||||
*/
|
||||
add(job) {
|
||||
this.jobs.push(job);
|
||||
this[kRun]();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job from the queue and runs it if possible.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
[kRun]() {
|
||||
if (this.pending === this.concurrency) return;
|
||||
|
||||
if (this.jobs.length) {
|
||||
const job = this.jobs.shift();
|
||||
|
||||
this.pending++;
|
||||
job(this[kDone]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Limiter;
|
||||
518
WebUI/node_modules/mqtt/node_modules/ws/lib/permessage-deflate.js
generated
vendored
Normal file
518
WebUI/node_modules/mqtt/node_modules/ws/lib/permessage-deflate.js
generated
vendored
Normal file
@@ -0,0 +1,518 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
|
||||
const bufferUtil = require('./buffer-util');
|
||||
const Limiter = require('./limiter');
|
||||
const { kStatusCode, NOOP } = require('./constants');
|
||||
|
||||
const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
|
||||
const kPerMessageDeflate = Symbol('permessage-deflate');
|
||||
const kTotalLength = Symbol('total-length');
|
||||
const kCallback = Symbol('callback');
|
||||
const kBuffers = Symbol('buffers');
|
||||
const kError = Symbol('error');
|
||||
|
||||
//
|
||||
// We limit zlib concurrency, which prevents severe memory fragmentation
|
||||
// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913
|
||||
// and https://github.com/websockets/ws/issues/1202
|
||||
//
|
||||
// Intentionally global; it's the global thread pool that's an issue.
|
||||
//
|
||||
let zlibLimiter;
|
||||
|
||||
/**
|
||||
* permessage-deflate implementation.
|
||||
*/
|
||||
class PerMessageDeflate {
|
||||
/**
|
||||
* Creates a PerMessageDeflate instance.
|
||||
*
|
||||
* @param {Object} [options] Configuration options
|
||||
* @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
|
||||
* disabling of server context takeover
|
||||
* @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
|
||||
* acknowledge disabling of client context takeover
|
||||
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
|
||||
* use of a custom server window size
|
||||
* @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
|
||||
* for, or request, a custom client window size
|
||||
* @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
|
||||
* deflate
|
||||
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
|
||||
* inflate
|
||||
* @param {Number} [options.threshold=1024] Size (in bytes) below which
|
||||
* messages should not be compressed
|
||||
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
|
||||
* calls to zlib
|
||||
* @param {Boolean} [isServer=false] Create the instance in either server or
|
||||
* client mode
|
||||
* @param {Number} [maxPayload=0] The maximum allowed message length
|
||||
*/
|
||||
constructor(options, isServer, maxPayload) {
|
||||
this._maxPayload = maxPayload | 0;
|
||||
this._options = options || {};
|
||||
this._threshold =
|
||||
this._options.threshold !== undefined ? this._options.threshold : 1024;
|
||||
this._isServer = !!isServer;
|
||||
this._deflate = null;
|
||||
this._inflate = null;
|
||||
|
||||
this.params = null;
|
||||
|
||||
if (!zlibLimiter) {
|
||||
const concurrency =
|
||||
this._options.concurrencyLimit !== undefined
|
||||
? this._options.concurrencyLimit
|
||||
: 10;
|
||||
zlibLimiter = new Limiter(concurrency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {String}
|
||||
*/
|
||||
static get extensionName() {
|
||||
return 'permessage-deflate';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an extension negotiation offer.
|
||||
*
|
||||
* @return {Object} Extension parameters
|
||||
* @public
|
||||
*/
|
||||
offer() {
|
||||
const params = {};
|
||||
|
||||
if (this._options.serverNoContextTakeover) {
|
||||
params.server_no_context_takeover = true;
|
||||
}
|
||||
if (this._options.clientNoContextTakeover) {
|
||||
params.client_no_context_takeover = true;
|
||||
}
|
||||
if (this._options.serverMaxWindowBits) {
|
||||
params.server_max_window_bits = this._options.serverMaxWindowBits;
|
||||
}
|
||||
if (this._options.clientMaxWindowBits) {
|
||||
params.client_max_window_bits = this._options.clientMaxWindowBits;
|
||||
} else if (this._options.clientMaxWindowBits == null) {
|
||||
params.client_max_window_bits = true;
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an extension negotiation offer/response.
|
||||
*
|
||||
* @param {Array} configurations The extension negotiation offers/reponse
|
||||
* @return {Object} Accepted configuration
|
||||
* @public
|
||||
*/
|
||||
accept(configurations) {
|
||||
configurations = this.normalizeParams(configurations);
|
||||
|
||||
this.params = this._isServer
|
||||
? this.acceptAsServer(configurations)
|
||||
: this.acceptAsClient(configurations);
|
||||
|
||||
return this.params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources used by the extension.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
cleanup() {
|
||||
if (this._inflate) {
|
||||
this._inflate.close();
|
||||
this._inflate = null;
|
||||
}
|
||||
|
||||
if (this._deflate) {
|
||||
const callback = this._deflate[kCallback];
|
||||
|
||||
this._deflate.close();
|
||||
this._deflate = null;
|
||||
|
||||
if (callback) {
|
||||
callback(
|
||||
new Error(
|
||||
'The deflate stream was closed while data was being processed'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an extension negotiation offer.
|
||||
*
|
||||
* @param {Array} offers The extension negotiation offers
|
||||
* @return {Object} Accepted configuration
|
||||
* @private
|
||||
*/
|
||||
acceptAsServer(offers) {
|
||||
const opts = this._options;
|
||||
const accepted = offers.find((params) => {
|
||||
if (
|
||||
(opts.serverNoContextTakeover === false &&
|
||||
params.server_no_context_takeover) ||
|
||||
(params.server_max_window_bits &&
|
||||
(opts.serverMaxWindowBits === false ||
|
||||
(typeof opts.serverMaxWindowBits === 'number' &&
|
||||
opts.serverMaxWindowBits > params.server_max_window_bits))) ||
|
||||
(typeof opts.clientMaxWindowBits === 'number' &&
|
||||
!params.client_max_window_bits)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!accepted) {
|
||||
throw new Error('None of the extension offers can be accepted');
|
||||
}
|
||||
|
||||
if (opts.serverNoContextTakeover) {
|
||||
accepted.server_no_context_takeover = true;
|
||||
}
|
||||
if (opts.clientNoContextTakeover) {
|
||||
accepted.client_no_context_takeover = true;
|
||||
}
|
||||
if (typeof opts.serverMaxWindowBits === 'number') {
|
||||
accepted.server_max_window_bits = opts.serverMaxWindowBits;
|
||||
}
|
||||
if (typeof opts.clientMaxWindowBits === 'number') {
|
||||
accepted.client_max_window_bits = opts.clientMaxWindowBits;
|
||||
} else if (
|
||||
accepted.client_max_window_bits === true ||
|
||||
opts.clientMaxWindowBits === false
|
||||
) {
|
||||
delete accepted.client_max_window_bits;
|
||||
}
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the extension negotiation response.
|
||||
*
|
||||
* @param {Array} response The extension negotiation response
|
||||
* @return {Object} Accepted configuration
|
||||
* @private
|
||||
*/
|
||||
acceptAsClient(response) {
|
||||
const params = response[0];
|
||||
|
||||
if (
|
||||
this._options.clientNoContextTakeover === false &&
|
||||
params.client_no_context_takeover
|
||||
) {
|
||||
throw new Error('Unexpected parameter "client_no_context_takeover"');
|
||||
}
|
||||
|
||||
if (!params.client_max_window_bits) {
|
||||
if (typeof this._options.clientMaxWindowBits === 'number') {
|
||||
params.client_max_window_bits = this._options.clientMaxWindowBits;
|
||||
}
|
||||
} else if (
|
||||
this._options.clientMaxWindowBits === false ||
|
||||
(typeof this._options.clientMaxWindowBits === 'number' &&
|
||||
params.client_max_window_bits > this._options.clientMaxWindowBits)
|
||||
) {
|
||||
throw new Error(
|
||||
'Unexpected or invalid parameter "client_max_window_bits"'
|
||||
);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize parameters.
|
||||
*
|
||||
* @param {Array} configurations The extension negotiation offers/reponse
|
||||
* @return {Array} The offers/response with normalized parameters
|
||||
* @private
|
||||
*/
|
||||
normalizeParams(configurations) {
|
||||
configurations.forEach((params) => {
|
||||
Object.keys(params).forEach((key) => {
|
||||
let value = params[key];
|
||||
|
||||
if (value.length > 1) {
|
||||
throw new Error(`Parameter "${key}" must have only a single value`);
|
||||
}
|
||||
|
||||
value = value[0];
|
||||
|
||||
if (key === 'client_max_window_bits') {
|
||||
if (value !== true) {
|
||||
const num = +value;
|
||||
if (!Number.isInteger(num) || num < 8 || num > 15) {
|
||||
throw new TypeError(
|
||||
`Invalid value for parameter "${key}": ${value}`
|
||||
);
|
||||
}
|
||||
value = num;
|
||||
} else if (!this._isServer) {
|
||||
throw new TypeError(
|
||||
`Invalid value for parameter "${key}": ${value}`
|
||||
);
|
||||
}
|
||||
} else if (key === 'server_max_window_bits') {
|
||||
const num = +value;
|
||||
if (!Number.isInteger(num) || num < 8 || num > 15) {
|
||||
throw new TypeError(
|
||||
`Invalid value for parameter "${key}": ${value}`
|
||||
);
|
||||
}
|
||||
value = num;
|
||||
} else if (
|
||||
key === 'client_no_context_takeover' ||
|
||||
key === 'server_no_context_takeover'
|
||||
) {
|
||||
if (value !== true) {
|
||||
throw new TypeError(
|
||||
`Invalid value for parameter "${key}": ${value}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unknown parameter "${key}"`);
|
||||
}
|
||||
|
||||
params[key] = value;
|
||||
});
|
||||
});
|
||||
|
||||
return configurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress data. Concurrency limited.
|
||||
*
|
||||
* @param {Buffer} data Compressed data
|
||||
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
||||
* @param {Function} callback Callback
|
||||
* @public
|
||||
*/
|
||||
decompress(data, fin, callback) {
|
||||
zlibLimiter.add((done) => {
|
||||
this._decompress(data, fin, (err, result) => {
|
||||
done();
|
||||
callback(err, result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress data. Concurrency limited.
|
||||
*
|
||||
* @param {Buffer} data Data to compress
|
||||
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
||||
* @param {Function} callback Callback
|
||||
* @public
|
||||
*/
|
||||
compress(data, fin, callback) {
|
||||
zlibLimiter.add((done) => {
|
||||
this._compress(data, fin, (err, result) => {
|
||||
done();
|
||||
callback(err, result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress data.
|
||||
*
|
||||
* @param {Buffer} data Compressed data
|
||||
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
||||
* @param {Function} callback Callback
|
||||
* @private
|
||||
*/
|
||||
_decompress(data, fin, callback) {
|
||||
const endpoint = this._isServer ? 'client' : 'server';
|
||||
|
||||
if (!this._inflate) {
|
||||
const key = `${endpoint}_max_window_bits`;
|
||||
const windowBits =
|
||||
typeof this.params[key] !== 'number'
|
||||
? zlib.Z_DEFAULT_WINDOWBITS
|
||||
: this.params[key];
|
||||
|
||||
this._inflate = zlib.createInflateRaw({
|
||||
...this._options.zlibInflateOptions,
|
||||
windowBits
|
||||
});
|
||||
this._inflate[kPerMessageDeflate] = this;
|
||||
this._inflate[kTotalLength] = 0;
|
||||
this._inflate[kBuffers] = [];
|
||||
this._inflate.on('error', inflateOnError);
|
||||
this._inflate.on('data', inflateOnData);
|
||||
}
|
||||
|
||||
this._inflate[kCallback] = callback;
|
||||
|
||||
this._inflate.write(data);
|
||||
if (fin) this._inflate.write(TRAILER);
|
||||
|
||||
this._inflate.flush(() => {
|
||||
const err = this._inflate[kError];
|
||||
|
||||
if (err) {
|
||||
this._inflate.close();
|
||||
this._inflate = null;
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = bufferUtil.concat(
|
||||
this._inflate[kBuffers],
|
||||
this._inflate[kTotalLength]
|
||||
);
|
||||
|
||||
if (this._inflate._readableState.endEmitted) {
|
||||
this._inflate.close();
|
||||
this._inflate = null;
|
||||
} else {
|
||||
this._inflate[kTotalLength] = 0;
|
||||
this._inflate[kBuffers] = [];
|
||||
|
||||
if (fin && this.params[`${endpoint}_no_context_takeover`]) {
|
||||
this._inflate.reset();
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress data.
|
||||
*
|
||||
* @param {Buffer} data Data to compress
|
||||
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
||||
* @param {Function} callback Callback
|
||||
* @private
|
||||
*/
|
||||
_compress(data, fin, callback) {
|
||||
const endpoint = this._isServer ? 'server' : 'client';
|
||||
|
||||
if (!this._deflate) {
|
||||
const key = `${endpoint}_max_window_bits`;
|
||||
const windowBits =
|
||||
typeof this.params[key] !== 'number'
|
||||
? zlib.Z_DEFAULT_WINDOWBITS
|
||||
: this.params[key];
|
||||
|
||||
this._deflate = zlib.createDeflateRaw({
|
||||
...this._options.zlibDeflateOptions,
|
||||
windowBits
|
||||
});
|
||||
|
||||
this._deflate[kTotalLength] = 0;
|
||||
this._deflate[kBuffers] = [];
|
||||
|
||||
//
|
||||
// An `'error'` event is emitted, only on Node.js < 10.0.0, if the
|
||||
// `zlib.DeflateRaw` instance is closed while data is being processed.
|
||||
// This can happen if `PerMessageDeflate#cleanup()` is called at the wrong
|
||||
// time due to an abnormal WebSocket closure.
|
||||
//
|
||||
this._deflate.on('error', NOOP);
|
||||
this._deflate.on('data', deflateOnData);
|
||||
}
|
||||
|
||||
this._deflate[kCallback] = callback;
|
||||
|
||||
this._deflate.write(data);
|
||||
this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
|
||||
if (!this._deflate) {
|
||||
//
|
||||
// The deflate stream was closed while data was being processed.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
let data = bufferUtil.concat(
|
||||
this._deflate[kBuffers],
|
||||
this._deflate[kTotalLength]
|
||||
);
|
||||
|
||||
if (fin) data = data.slice(0, data.length - 4);
|
||||
|
||||
//
|
||||
// Ensure that the callback will not be called again in
|
||||
// `PerMessageDeflate#cleanup()`.
|
||||
//
|
||||
this._deflate[kCallback] = null;
|
||||
|
||||
this._deflate[kTotalLength] = 0;
|
||||
this._deflate[kBuffers] = [];
|
||||
|
||||
if (fin && this.params[`${endpoint}_no_context_takeover`]) {
|
||||
this._deflate.reset();
|
||||
}
|
||||
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PerMessageDeflate;
|
||||
|
||||
/**
|
||||
* The listener of the `zlib.DeflateRaw` stream `'data'` event.
|
||||
*
|
||||
* @param {Buffer} chunk A chunk of data
|
||||
* @private
|
||||
*/
|
||||
function deflateOnData(chunk) {
|
||||
this[kBuffers].push(chunk);
|
||||
this[kTotalLength] += chunk.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* The listener of the `zlib.InflateRaw` stream `'data'` event.
|
||||
*
|
||||
* @param {Buffer} chunk A chunk of data
|
||||
* @private
|
||||
*/
|
||||
function inflateOnData(chunk) {
|
||||
this[kTotalLength] += chunk.length;
|
||||
|
||||
if (
|
||||
this[kPerMessageDeflate]._maxPayload < 1 ||
|
||||
this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload
|
||||
) {
|
||||
this[kBuffers].push(chunk);
|
||||
return;
|
||||
}
|
||||
|
||||
this[kError] = new RangeError('Max payload size exceeded');
|
||||
this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
|
||||
this[kError][kStatusCode] = 1009;
|
||||
this.removeListener('data', inflateOnData);
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* The listener of the `zlib.InflateRaw` stream `'error'` event.
|
||||
*
|
||||
* @param {Error} err The emitted error
|
||||
* @private
|
||||
*/
|
||||
function inflateOnError(err) {
|
||||
//
|
||||
// There is no need to call `Zlib#close()` as the handle is automatically
|
||||
// closed when an error is emitted.
|
||||
//
|
||||
this[kPerMessageDeflate]._inflate = null;
|
||||
err[kStatusCode] = 1007;
|
||||
this[kCallback](err);
|
||||
}
|
||||
607
WebUI/node_modules/mqtt/node_modules/ws/lib/receiver.js
generated
vendored
Normal file
607
WebUI/node_modules/mqtt/node_modules/ws/lib/receiver.js
generated
vendored
Normal file
@@ -0,0 +1,607 @@
|
||||
'use strict';
|
||||
|
||||
const { Writable } = require('stream');
|
||||
|
||||
const PerMessageDeflate = require('./permessage-deflate');
|
||||
const {
|
||||
BINARY_TYPES,
|
||||
EMPTY_BUFFER,
|
||||
kStatusCode,
|
||||
kWebSocket
|
||||
} = require('./constants');
|
||||
const { concat, toArrayBuffer, unmask } = require('./buffer-util');
|
||||
const { isValidStatusCode, isValidUTF8 } = require('./validation');
|
||||
|
||||
const GET_INFO = 0;
|
||||
const GET_PAYLOAD_LENGTH_16 = 1;
|
||||
const GET_PAYLOAD_LENGTH_64 = 2;
|
||||
const GET_MASK = 3;
|
||||
const GET_DATA = 4;
|
||||
const INFLATING = 5;
|
||||
|
||||
/**
|
||||
* HyBi Receiver implementation.
|
||||
*
|
||||
* @extends Writable
|
||||
*/
|
||||
class Receiver extends Writable {
|
||||
/**
|
||||
* Creates a Receiver instance.
|
||||
*
|
||||
* @param {String} [binaryType=nodebuffer] The type for binary data
|
||||
* @param {Object} [extensions] An object containing the negotiated extensions
|
||||
* @param {Boolean} [isServer=false] Specifies whether to operate in client or
|
||||
* server mode
|
||||
* @param {Number} [maxPayload=0] The maximum allowed message length
|
||||
*/
|
||||
constructor(binaryType, extensions, isServer, maxPayload) {
|
||||
super();
|
||||
|
||||
this._binaryType = binaryType || BINARY_TYPES[0];
|
||||
this[kWebSocket] = undefined;
|
||||
this._extensions = extensions || {};
|
||||
this._isServer = !!isServer;
|
||||
this._maxPayload = maxPayload | 0;
|
||||
|
||||
this._bufferedBytes = 0;
|
||||
this._buffers = [];
|
||||
|
||||
this._compressed = false;
|
||||
this._payloadLength = 0;
|
||||
this._mask = undefined;
|
||||
this._fragmented = 0;
|
||||
this._masked = false;
|
||||
this._fin = false;
|
||||
this._opcode = 0;
|
||||
|
||||
this._totalPayloadLength = 0;
|
||||
this._messageLength = 0;
|
||||
this._fragments = [];
|
||||
|
||||
this._state = GET_INFO;
|
||||
this._loop = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements `Writable.prototype._write()`.
|
||||
*
|
||||
* @param {Buffer} chunk The chunk of data to write
|
||||
* @param {String} encoding The character encoding of `chunk`
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
_write(chunk, encoding, cb) {
|
||||
if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
|
||||
|
||||
this._bufferedBytes += chunk.length;
|
||||
this._buffers.push(chunk);
|
||||
this.startLoop(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes `n` bytes from the buffered data.
|
||||
*
|
||||
* @param {Number} n The number of bytes to consume
|
||||
* @return {Buffer} The consumed bytes
|
||||
* @private
|
||||
*/
|
||||
consume(n) {
|
||||
this._bufferedBytes -= n;
|
||||
|
||||
if (n === this._buffers[0].length) return this._buffers.shift();
|
||||
|
||||
if (n < this._buffers[0].length) {
|
||||
const buf = this._buffers[0];
|
||||
this._buffers[0] = buf.slice(n);
|
||||
return buf.slice(0, n);
|
||||
}
|
||||
|
||||
const dst = Buffer.allocUnsafe(n);
|
||||
|
||||
do {
|
||||
const buf = this._buffers[0];
|
||||
const offset = dst.length - n;
|
||||
|
||||
if (n >= buf.length) {
|
||||
dst.set(this._buffers.shift(), offset);
|
||||
} else {
|
||||
dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
|
||||
this._buffers[0] = buf.slice(n);
|
||||
}
|
||||
|
||||
n -= buf.length;
|
||||
} while (n > 0);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the parsing loop.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
startLoop(cb) {
|
||||
let err;
|
||||
this._loop = true;
|
||||
|
||||
do {
|
||||
switch (this._state) {
|
||||
case GET_INFO:
|
||||
err = this.getInfo();
|
||||
break;
|
||||
case GET_PAYLOAD_LENGTH_16:
|
||||
err = this.getPayloadLength16();
|
||||
break;
|
||||
case GET_PAYLOAD_LENGTH_64:
|
||||
err = this.getPayloadLength64();
|
||||
break;
|
||||
case GET_MASK:
|
||||
this.getMask();
|
||||
break;
|
||||
case GET_DATA:
|
||||
err = this.getData(cb);
|
||||
break;
|
||||
default:
|
||||
// `INFLATING`
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
} while (this._loop);
|
||||
|
||||
cb(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the first two bytes of a frame.
|
||||
*
|
||||
* @return {(RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
getInfo() {
|
||||
if (this._bufferedBytes < 2) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = this.consume(2);
|
||||
|
||||
if ((buf[0] & 0x30) !== 0x00) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'RSV2 and RSV3 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_2_3'
|
||||
);
|
||||
}
|
||||
|
||||
const compressed = (buf[0] & 0x40) === 0x40;
|
||||
|
||||
if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
}
|
||||
|
||||
this._fin = (buf[0] & 0x80) === 0x80;
|
||||
this._opcode = buf[0] & 0x0f;
|
||||
this._payloadLength = buf[1] & 0x7f;
|
||||
|
||||
if (this._opcode === 0x00) {
|
||||
if (compressed) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
}
|
||||
|
||||
if (!this._fragmented) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'invalid opcode 0',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
}
|
||||
|
||||
this._opcode = this._fragmented;
|
||||
} else if (this._opcode === 0x01 || this._opcode === 0x02) {
|
||||
if (this._fragmented) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
`invalid opcode ${this._opcode}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
}
|
||||
|
||||
this._compressed = compressed;
|
||||
} else if (this._opcode > 0x07 && this._opcode < 0x0b) {
|
||||
if (!this._fin) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'FIN must be set',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_EXPECTED_FIN'
|
||||
);
|
||||
}
|
||||
|
||||
if (compressed) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'RSV1 must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_RSV_1'
|
||||
);
|
||||
}
|
||||
|
||||
if (this._payloadLength > 0x7d) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
`invalid payload length ${this._payloadLength}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
`invalid opcode ${this._opcode}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_OPCODE'
|
||||
);
|
||||
}
|
||||
|
||||
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
|
||||
this._masked = (buf[1] & 0x80) === 0x80;
|
||||
|
||||
if (this._isServer) {
|
||||
if (!this._masked) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'MASK must be set',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_EXPECTED_MASK'
|
||||
);
|
||||
}
|
||||
} else if (this._masked) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'MASK must be clear',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_UNEXPECTED_MASK'
|
||||
);
|
||||
}
|
||||
|
||||
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
|
||||
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
|
||||
else return this.haveLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extended payload length (7+16).
|
||||
*
|
||||
* @return {(RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
getPayloadLength16() {
|
||||
if (this._bufferedBytes < 2) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._payloadLength = this.consume(2).readUInt16BE(0);
|
||||
return this.haveLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extended payload length (7+64).
|
||||
*
|
||||
* @return {(RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
getPayloadLength64() {
|
||||
if (this._bufferedBytes < 8) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = this.consume(8);
|
||||
const num = buf.readUInt32BE(0);
|
||||
|
||||
//
|
||||
// The maximum safe integer in JavaScript is 2^53 - 1. An error is returned
|
||||
// if payload length is greater than this number.
|
||||
//
|
||||
if (num > Math.pow(2, 53 - 32) - 1) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'Unsupported WebSocket frame: payload length > 2^53 - 1',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
|
||||
);
|
||||
}
|
||||
|
||||
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
|
||||
return this.haveLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload length has been read.
|
||||
*
|
||||
* @return {(RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
haveLength() {
|
||||
if (this._payloadLength && this._opcode < 0x08) {
|
||||
this._totalPayloadLength += this._payloadLength;
|
||||
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
RangeError,
|
||||
'Max payload size exceeded',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._masked) this._state = GET_MASK;
|
||||
else this._state = GET_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads mask bytes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
getMask() {
|
||||
if (this._bufferedBytes < 4) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._mask = this.consume(4);
|
||||
this._state = GET_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data bytes.
|
||||
*
|
||||
* @param {Function} cb Callback
|
||||
* @return {(Error|RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
getData(cb) {
|
||||
let data = EMPTY_BUFFER;
|
||||
|
||||
if (this._payloadLength) {
|
||||
if (this._bufferedBytes < this._payloadLength) {
|
||||
this._loop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
data = this.consume(this._payloadLength);
|
||||
if (this._masked) unmask(data, this._mask);
|
||||
}
|
||||
|
||||
if (this._opcode > 0x07) return this.controlMessage(data);
|
||||
|
||||
if (this._compressed) {
|
||||
this._state = INFLATING;
|
||||
this.decompress(data, cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.length) {
|
||||
//
|
||||
// This message is not compressed so its lenght is the sum of the payload
|
||||
// length of all fragments.
|
||||
//
|
||||
this._messageLength = this._totalPayloadLength;
|
||||
this._fragments.push(data);
|
||||
}
|
||||
|
||||
return this.dataMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses data.
|
||||
*
|
||||
* @param {Buffer} data Compressed data
|
||||
* @param {Function} cb Callback
|
||||
* @private
|
||||
*/
|
||||
decompress(data, cb) {
|
||||
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
||||
|
||||
perMessageDeflate.decompress(data, this._fin, (err, buf) => {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (buf.length) {
|
||||
this._messageLength += buf.length;
|
||||
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
|
||||
return cb(
|
||||
error(
|
||||
RangeError,
|
||||
'Max payload size exceeded',
|
||||
false,
|
||||
1009,
|
||||
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
this._fragments.push(buf);
|
||||
}
|
||||
|
||||
const er = this.dataMessage();
|
||||
if (er) return cb(er);
|
||||
|
||||
this.startLoop(cb);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a data message.
|
||||
*
|
||||
* @return {(Error|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
dataMessage() {
|
||||
if (this._fin) {
|
||||
const messageLength = this._messageLength;
|
||||
const fragments = this._fragments;
|
||||
|
||||
this._totalPayloadLength = 0;
|
||||
this._messageLength = 0;
|
||||
this._fragmented = 0;
|
||||
this._fragments = [];
|
||||
|
||||
if (this._opcode === 2) {
|
||||
let data;
|
||||
|
||||
if (this._binaryType === 'nodebuffer') {
|
||||
data = concat(fragments, messageLength);
|
||||
} else if (this._binaryType === 'arraybuffer') {
|
||||
data = toArrayBuffer(concat(fragments, messageLength));
|
||||
} else {
|
||||
data = fragments;
|
||||
}
|
||||
|
||||
this.emit('message', data);
|
||||
} else {
|
||||
const buf = concat(fragments, messageLength);
|
||||
|
||||
if (!isValidUTF8(buf)) {
|
||||
this._loop = false;
|
||||
return error(
|
||||
Error,
|
||||
'invalid UTF-8 sequence',
|
||||
true,
|
||||
1007,
|
||||
'WS_ERR_INVALID_UTF8'
|
||||
);
|
||||
}
|
||||
|
||||
this.emit('message', buf.toString());
|
||||
}
|
||||
}
|
||||
|
||||
this._state = GET_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a control message.
|
||||
*
|
||||
* @param {Buffer} data Data to handle
|
||||
* @return {(Error|RangeError|undefined)} A possible error
|
||||
* @private
|
||||
*/
|
||||
controlMessage(data) {
|
||||
if (this._opcode === 0x08) {
|
||||
this._loop = false;
|
||||
|
||||
if (data.length === 0) {
|
||||
this.emit('conclude', 1005, '');
|
||||
this.end();
|
||||
} else if (data.length === 1) {
|
||||
return error(
|
||||
RangeError,
|
||||
'invalid payload length 1',
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
||||
);
|
||||
} else {
|
||||
const code = data.readUInt16BE(0);
|
||||
|
||||
if (!isValidStatusCode(code)) {
|
||||
return error(
|
||||
RangeError,
|
||||
`invalid status code ${code}`,
|
||||
true,
|
||||
1002,
|
||||
'WS_ERR_INVALID_CLOSE_CODE'
|
||||
);
|
||||
}
|
||||
|
||||
const buf = data.slice(2);
|
||||
|
||||
if (!isValidUTF8(buf)) {
|
||||
return error(
|
||||
Error,
|
||||
'invalid UTF-8 sequence',
|
||||
true,
|
||||
1007,
|
||||
'WS_ERR_INVALID_UTF8'
|
||||
);
|
||||
}
|
||||
|
||||
this.emit('conclude', code, buf.toString());
|
||||
this.end();
|
||||
}
|
||||
} else if (this._opcode === 0x09) {
|
||||
this.emit('ping', data);
|
||||
} else {
|
||||
this.emit('pong', data);
|
||||
}
|
||||
|
||||
this._state = GET_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Receiver;
|
||||
|
||||
/**
|
||||
* Builds an error object.
|
||||
*
|
||||
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
|
||||
* @param {String} message The error message
|
||||
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
|
||||
* `message`
|
||||
* @param {Number} statusCode The status code
|
||||
* @param {String} errorCode The exposed error code
|
||||
* @return {(Error|RangeError)} The error
|
||||
* @private
|
||||
*/
|
||||
function error(ErrorCtor, message, prefix, statusCode, errorCode) {
|
||||
const err = new ErrorCtor(
|
||||
prefix ? `Invalid WebSocket frame: ${message}` : message
|
||||
);
|
||||
|
||||
Error.captureStackTrace(err, error);
|
||||
err.code = errorCode;
|
||||
err[kStatusCode] = statusCode;
|
||||
return err;
|
||||
}
|
||||
409
WebUI/node_modules/mqtt/node_modules/ws/lib/sender.js
generated
vendored
Normal file
409
WebUI/node_modules/mqtt/node_modules/ws/lib/sender.js
generated
vendored
Normal file
@@ -0,0 +1,409 @@
|
||||
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls$" }] */
|
||||
|
||||
'use strict';
|
||||
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const { randomFillSync } = require('crypto');
|
||||
|
||||
const PerMessageDeflate = require('./permessage-deflate');
|
||||
const { EMPTY_BUFFER } = require('./constants');
|
||||
const { isValidStatusCode } = require('./validation');
|
||||
const { mask: applyMask, toBuffer } = require('./buffer-util');
|
||||
|
||||
const mask = Buffer.alloc(4);
|
||||
|
||||
/**
|
||||
* HyBi Sender implementation.
|
||||
*/
|
||||
class Sender {
|
||||
/**
|
||||
* Creates a Sender instance.
|
||||
*
|
||||
* @param {(net.Socket|tls.Socket)} socket The connection socket
|
||||
* @param {Object} [extensions] An object containing the negotiated extensions
|
||||
*/
|
||||
constructor(socket, extensions) {
|
||||
this._extensions = extensions || {};
|
||||
this._socket = socket;
|
||||
|
||||
this._firstFragment = true;
|
||||
this._compress = false;
|
||||
|
||||
this._bufferedBytes = 0;
|
||||
this._deflating = false;
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Frames a piece of data according to the HyBi WebSocket protocol.
|
||||
*
|
||||
* @param {Buffer} data The data to frame
|
||||
* @param {Object} options Options object
|
||||
* @param {Number} options.opcode The opcode
|
||||
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
||||
* modified
|
||||
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
|
||||
* FIN bit
|
||||
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
||||
* `data`
|
||||
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
|
||||
* RSV1 bit
|
||||
* @return {Buffer[]} The framed data as a list of `Buffer` instances
|
||||
* @public
|
||||
*/
|
||||
static frame(data, options) {
|
||||
const merge = options.mask && options.readOnly;
|
||||
let offset = options.mask ? 6 : 2;
|
||||
let payloadLength = data.length;
|
||||
|
||||
if (data.length >= 65536) {
|
||||
offset += 8;
|
||||
payloadLength = 127;
|
||||
} else if (data.length > 125) {
|
||||
offset += 2;
|
||||
payloadLength = 126;
|
||||
}
|
||||
|
||||
const target = Buffer.allocUnsafe(merge ? data.length + offset : offset);
|
||||
|
||||
target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
|
||||
if (options.rsv1) target[0] |= 0x40;
|
||||
|
||||
target[1] = payloadLength;
|
||||
|
||||
if (payloadLength === 126) {
|
||||
target.writeUInt16BE(data.length, 2);
|
||||
} else if (payloadLength === 127) {
|
||||
target.writeUInt32BE(0, 2);
|
||||
target.writeUInt32BE(data.length, 6);
|
||||
}
|
||||
|
||||
if (!options.mask) return [target, data];
|
||||
|
||||
randomFillSync(mask, 0, 4);
|
||||
|
||||
target[1] |= 0x80;
|
||||
target[offset - 4] = mask[0];
|
||||
target[offset - 3] = mask[1];
|
||||
target[offset - 2] = mask[2];
|
||||
target[offset - 1] = mask[3];
|
||||
|
||||
if (merge) {
|
||||
applyMask(data, mask, target, offset, data.length);
|
||||
return [target];
|
||||
}
|
||||
|
||||
applyMask(data, mask, data, 0, data.length);
|
||||
return [target, data];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a close message to the other peer.
|
||||
*
|
||||
* @param {Number} [code] The status code component of the body
|
||||
* @param {String} [data] The message component of the body
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask the message
|
||||
* @param {Function} [cb] Callback
|
||||
* @public
|
||||
*/
|
||||
close(code, data, mask, cb) {
|
||||
let buf;
|
||||
|
||||
if (code === undefined) {
|
||||
buf = EMPTY_BUFFER;
|
||||
} else if (typeof code !== 'number' || !isValidStatusCode(code)) {
|
||||
throw new TypeError('First argument must be a valid error code number');
|
||||
} else if (data === undefined || data === '') {
|
||||
buf = Buffer.allocUnsafe(2);
|
||||
buf.writeUInt16BE(code, 0);
|
||||
} else {
|
||||
const length = Buffer.byteLength(data);
|
||||
|
||||
if (length > 123) {
|
||||
throw new RangeError('The message must not be greater than 123 bytes');
|
||||
}
|
||||
|
||||
buf = Buffer.allocUnsafe(2 + length);
|
||||
buf.writeUInt16BE(code, 0);
|
||||
buf.write(data, 2);
|
||||
}
|
||||
|
||||
if (this._deflating) {
|
||||
this.enqueue([this.doClose, buf, mask, cb]);
|
||||
} else {
|
||||
this.doClose(buf, mask, cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frames and sends a close message.
|
||||
*
|
||||
* @param {Buffer} data The message to send
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
||||
* @param {Function} [cb] Callback
|
||||
* @private
|
||||
*/
|
||||
doClose(data, mask, cb) {
|
||||
this.sendFrame(
|
||||
Sender.frame(data, {
|
||||
fin: true,
|
||||
rsv1: false,
|
||||
opcode: 0x08,
|
||||
mask,
|
||||
readOnly: false
|
||||
}),
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a ping message to the other peer.
|
||||
*
|
||||
* @param {*} data The message to send
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
||||
* @param {Function} [cb] Callback
|
||||
* @public
|
||||
*/
|
||||
ping(data, mask, cb) {
|
||||
const buf = toBuffer(data);
|
||||
|
||||
if (buf.length > 125) {
|
||||
throw new RangeError('The data size must not be greater than 125 bytes');
|
||||
}
|
||||
|
||||
if (this._deflating) {
|
||||
this.enqueue([this.doPing, buf, mask, toBuffer.readOnly, cb]);
|
||||
} else {
|
||||
this.doPing(buf, mask, toBuffer.readOnly, cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frames and sends a ping message.
|
||||
*
|
||||
* @param {Buffer} data The message to send
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
||||
* @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
|
||||
* @param {Function} [cb] Callback
|
||||
* @private
|
||||
*/
|
||||
doPing(data, mask, readOnly, cb) {
|
||||
this.sendFrame(
|
||||
Sender.frame(data, {
|
||||
fin: true,
|
||||
rsv1: false,
|
||||
opcode: 0x09,
|
||||
mask,
|
||||
readOnly
|
||||
}),
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a pong message to the other peer.
|
||||
*
|
||||
* @param {*} data The message to send
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
||||
* @param {Function} [cb] Callback
|
||||
* @public
|
||||
*/
|
||||
pong(data, mask, cb) {
|
||||
const buf = toBuffer(data);
|
||||
|
||||
if (buf.length > 125) {
|
||||
throw new RangeError('The data size must not be greater than 125 bytes');
|
||||
}
|
||||
|
||||
if (this._deflating) {
|
||||
this.enqueue([this.doPong, buf, mask, toBuffer.readOnly, cb]);
|
||||
} else {
|
||||
this.doPong(buf, mask, toBuffer.readOnly, cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frames and sends a pong message.
|
||||
*
|
||||
* @param {Buffer} data The message to send
|
||||
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
||||
* @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
|
||||
* @param {Function} [cb] Callback
|
||||
* @private
|
||||
*/
|
||||
doPong(data, mask, readOnly, cb) {
|
||||
this.sendFrame(
|
||||
Sender.frame(data, {
|
||||
fin: true,
|
||||
rsv1: false,
|
||||
opcode: 0x0a,
|
||||
mask,
|
||||
readOnly
|
||||
}),
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a data message to the other peer.
|
||||
*
|
||||
* @param {*} data The message to send
|
||||
* @param {Object} options Options object
|
||||
* @param {Boolean} [options.compress=false] Specifies whether or not to
|
||||
* compress `data`
|
||||
* @param {Boolean} [options.binary=false] Specifies whether `data` is binary
|
||||
* or text
|
||||
* @param {Boolean} [options.fin=false] Specifies whether the fragment is the
|
||||
* last one
|
||||
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
||||
* `data`
|
||||
* @param {Function} [cb] Callback
|
||||
* @public
|
||||
*/
|
||||
send(data, options, cb) {
|
||||
const buf = toBuffer(data);
|
||||
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
||||
let opcode = options.binary ? 2 : 1;
|
||||
let rsv1 = options.compress;
|
||||
|
||||
if (this._firstFragment) {
|
||||
this._firstFragment = false;
|
||||
if (rsv1 && perMessageDeflate) {
|
||||
rsv1 = buf.length >= perMessageDeflate._threshold;
|
||||
}
|
||||
this._compress = rsv1;
|
||||
} else {
|
||||
rsv1 = false;
|
||||
opcode = 0;
|
||||
}
|
||||
|
||||
if (options.fin) this._firstFragment = true;
|
||||
|
||||
if (perMessageDeflate) {
|
||||
const opts = {
|
||||
fin: options.fin,
|
||||
rsv1,
|
||||
opcode,
|
||||
mask: options.mask,
|
||||
readOnly: toBuffer.readOnly
|
||||
};
|
||||
|
||||
if (this._deflating) {
|
||||
this.enqueue([this.dispatch, buf, this._compress, opts, cb]);
|
||||
} else {
|
||||
this.dispatch(buf, this._compress, opts, cb);
|
||||
}
|
||||
} else {
|
||||
this.sendFrame(
|
||||
Sender.frame(buf, {
|
||||
fin: options.fin,
|
||||
rsv1: false,
|
||||
opcode,
|
||||
mask: options.mask,
|
||||
readOnly: toBuffer.readOnly
|
||||
}),
|
||||
cb
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a data message.
|
||||
*
|
||||
* @param {Buffer} data The message to send
|
||||
* @param {Boolean} [compress=false] Specifies whether or not to compress
|
||||
* `data`
|
||||
* @param {Object} options Options object
|
||||
* @param {Number} options.opcode The opcode
|
||||
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
||||
* modified
|
||||
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
|
||||
* FIN bit
|
||||
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
||||
* `data`
|
||||
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
|
||||
* RSV1 bit
|
||||
* @param {Function} [cb] Callback
|
||||
* @private
|
||||
*/
|
||||
dispatch(data, compress, options, cb) {
|
||||
if (!compress) {
|
||||
this.sendFrame(Sender.frame(data, options), cb);
|
||||
return;
|
||||
}
|
||||
|
||||
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
||||
|
||||
this._bufferedBytes += data.length;
|
||||
this._deflating = true;
|
||||
perMessageDeflate.compress(data, options.fin, (_, buf) => {
|
||||
if (this._socket.destroyed) {
|
||||
const err = new Error(
|
||||
'The socket was closed while data was being compressed'
|
||||
);
|
||||
|
||||
if (typeof cb === 'function') cb(err);
|
||||
|
||||
for (let i = 0; i < this._queue.length; i++) {
|
||||
const callback = this._queue[i][4];
|
||||
|
||||
if (typeof callback === 'function') callback(err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._bufferedBytes -= data.length;
|
||||
this._deflating = false;
|
||||
options.readOnly = false;
|
||||
this.sendFrame(Sender.frame(buf, options), cb);
|
||||
this.dequeue();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes queued send operations.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
dequeue() {
|
||||
while (!this._deflating && this._queue.length) {
|
||||
const params = this._queue.shift();
|
||||
|
||||
this._bufferedBytes -= params[1].length;
|
||||
Reflect.apply(params[0], this, params.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues a send operation.
|
||||
*
|
||||
* @param {Array} params Send operation parameters.
|
||||
* @private
|
||||
*/
|
||||
enqueue(params) {
|
||||
this._bufferedBytes += params[1].length;
|
||||
this._queue.push(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a frame.
|
||||
*
|
||||
* @param {Buffer[]} list The frame to send
|
||||
* @param {Function} [cb] Callback
|
||||
* @private
|
||||
*/
|
||||
sendFrame(list, cb) {
|
||||
if (list.length === 2) {
|
||||
this._socket.cork();
|
||||
this._socket.write(list[0]);
|
||||
this._socket.write(list[1], cb);
|
||||
this._socket.uncork();
|
||||
} else {
|
||||
this._socket.write(list[0], cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Sender;
|
||||
180
WebUI/node_modules/mqtt/node_modules/ws/lib/stream.js
generated
vendored
Normal file
180
WebUI/node_modules/mqtt/node_modules/ws/lib/stream.js
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
'use strict';
|
||||
|
||||
const { Duplex } = require('stream');
|
||||
|
||||
/**
|
||||
* Emits the `'close'` event on a stream.
|
||||
*
|
||||
* @param {Duplex} stream The stream.
|
||||
* @private
|
||||
*/
|
||||
function emitClose(stream) {
|
||||
stream.emit('close');
|
||||
}
|
||||
|
||||
/**
|
||||
* The listener of the `'end'` event.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function duplexOnEnd() {
|
||||
if (!this.destroyed && this._writableState.finished) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The listener of the `'error'` event.
|
||||
*
|
||||
* @param {Error} err The error
|
||||
* @private
|
||||
*/
|
||||
function duplexOnError(err) {
|
||||
this.removeListener('error', duplexOnError);
|
||||
this.destroy();
|
||||
if (this.listenerCount('error') === 0) {
|
||||
// Do not suppress the throwing behavior.
|
||||
this.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a `WebSocket` in a duplex stream.
|
||||
*
|
||||
* @param {WebSocket} ws The `WebSocket` to wrap
|
||||
* @param {Object} [options] The options for the `Duplex` constructor
|
||||
* @return {Duplex} The duplex stream
|
||||
* @public
|
||||
*/
|
||||
function createWebSocketStream(ws, options) {
|
||||
let resumeOnReceiverDrain = true;
|
||||
let terminateOnDestroy = true;
|
||||
|
||||
function receiverOnDrain() {
|
||||
if (resumeOnReceiverDrain) ws._socket.resume();
|
||||
}
|
||||
|
||||
if (ws.readyState === ws.CONNECTING) {
|
||||
ws.once('open', function open() {
|
||||
ws._receiver.removeAllListeners('drain');
|
||||
ws._receiver.on('drain', receiverOnDrain);
|
||||
});
|
||||
} else {
|
||||
ws._receiver.removeAllListeners('drain');
|
||||
ws._receiver.on('drain', receiverOnDrain);
|
||||
}
|
||||
|
||||
const duplex = new Duplex({
|
||||
...options,
|
||||
autoDestroy: false,
|
||||
emitClose: false,
|
||||
objectMode: false,
|
||||
writableObjectMode: false
|
||||
});
|
||||
|
||||
ws.on('message', function message(msg) {
|
||||
if (!duplex.push(msg)) {
|
||||
resumeOnReceiverDrain = false;
|
||||
ws._socket.pause();
|
||||
}
|
||||
});
|
||||
|
||||
ws.once('error', function error(err) {
|
||||
if (duplex.destroyed) return;
|
||||
|
||||
// Prevent `ws.terminate()` from being called by `duplex._destroy()`.
|
||||
//
|
||||
// - If the `'error'` event is emitted before the `'open'` event, then
|
||||
// `ws.terminate()` is a noop as no socket is assigned.
|
||||
// - Otherwise, the error is re-emitted by the listener of the `'error'`
|
||||
// event of the `Receiver` object. The listener already closes the
|
||||
// connection by calling `ws.close()`. This allows a close frame to be
|
||||
// sent to the other peer. If `ws.terminate()` is called right after this,
|
||||
// then the close frame might not be sent.
|
||||
terminateOnDestroy = false;
|
||||
duplex.destroy(err);
|
||||
});
|
||||
|
||||
ws.once('close', function close() {
|
||||
if (duplex.destroyed) return;
|
||||
|
||||
duplex.push(null);
|
||||
});
|
||||
|
||||
duplex._destroy = function (err, callback) {
|
||||
if (ws.readyState === ws.CLOSED) {
|
||||
callback(err);
|
||||
process.nextTick(emitClose, duplex);
|
||||
return;
|
||||
}
|
||||
|
||||
let called = false;
|
||||
|
||||
ws.once('error', function error(err) {
|
||||
called = true;
|
||||
callback(err);
|
||||
});
|
||||
|
||||
ws.once('close', function close() {
|
||||
if (!called) callback(err);
|
||||
process.nextTick(emitClose, duplex);
|
||||
});
|
||||
|
||||
if (terminateOnDestroy) ws.terminate();
|
||||
};
|
||||
|
||||
duplex._final = function (callback) {
|
||||
if (ws.readyState === ws.CONNECTING) {
|
||||
ws.once('open', function open() {
|
||||
duplex._final(callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If the value of the `_socket` property is `null` it means that `ws` is a
|
||||
// client websocket and the handshake failed. In fact, when this happens, a
|
||||
// socket is never assigned to the websocket. Wait for the `'error'` event
|
||||
// that will be emitted by the websocket.
|
||||
if (ws._socket === null) return;
|
||||
|
||||
if (ws._socket._writableState.finished) {
|
||||
callback();
|
||||
if (duplex._readableState.endEmitted) duplex.destroy();
|
||||
} else {
|
||||
ws._socket.once('finish', function finish() {
|
||||
// `duplex` is not destroyed here because the `'end'` event will be
|
||||
// emitted on `duplex` after this `'finish'` event. The EOF signaling
|
||||
// `null` chunk is, in fact, pushed when the websocket emits `'close'`.
|
||||
callback();
|
||||
});
|
||||
ws.close();
|
||||
}
|
||||
};
|
||||
|
||||
duplex._read = function () {
|
||||
if (
|
||||
(ws.readyState === ws.OPEN || ws.readyState === ws.CLOSING) &&
|
||||
!resumeOnReceiverDrain
|
||||
) {
|
||||
resumeOnReceiverDrain = true;
|
||||
if (!ws._receiver._writableState.needDrain) ws._socket.resume();
|
||||
}
|
||||
};
|
||||
|
||||
duplex._write = function (chunk, encoding, callback) {
|
||||
if (ws.readyState === ws.CONNECTING) {
|
||||
ws.once('open', function open() {
|
||||
duplex._write(chunk, encoding, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ws.send(chunk, callback);
|
||||
};
|
||||
|
||||
duplex.on('end', duplexOnEnd);
|
||||
duplex.on('error', duplexOnError);
|
||||
return duplex;
|
||||
}
|
||||
|
||||
module.exports = createWebSocketStream;
|
||||
104
WebUI/node_modules/mqtt/node_modules/ws/lib/validation.js
generated
vendored
Normal file
104
WebUI/node_modules/mqtt/node_modules/ws/lib/validation.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Checks if a status code is allowed in a close frame.
|
||||
*
|
||||
* @param {Number} code The status code
|
||||
* @return {Boolean} `true` if the status code is valid, else `false`
|
||||
* @public
|
||||
*/
|
||||
function isValidStatusCode(code) {
|
||||
return (
|
||||
(code >= 1000 &&
|
||||
code <= 1014 &&
|
||||
code !== 1004 &&
|
||||
code !== 1005 &&
|
||||
code !== 1006) ||
|
||||
(code >= 3000 && code <= 4999)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given buffer contains only correct UTF-8.
|
||||
* Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
|
||||
* Markus Kuhn.
|
||||
*
|
||||
* @param {Buffer} buf The buffer to check
|
||||
* @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
|
||||
* @public
|
||||
*/
|
||||
function _isValidUTF8(buf) {
|
||||
const len = buf.length;
|
||||
let i = 0;
|
||||
|
||||
while (i < len) {
|
||||
if ((buf[i] & 0x80) === 0) {
|
||||
// 0xxxxxxx
|
||||
i++;
|
||||
} else if ((buf[i] & 0xe0) === 0xc0) {
|
||||
// 110xxxxx 10xxxxxx
|
||||
if (
|
||||
i + 1 === len ||
|
||||
(buf[i + 1] & 0xc0) !== 0x80 ||
|
||||
(buf[i] & 0xfe) === 0xc0 // Overlong
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i += 2;
|
||||
} else if ((buf[i] & 0xf0) === 0xe0) {
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
if (
|
||||
i + 2 >= len ||
|
||||
(buf[i + 1] & 0xc0) !== 0x80 ||
|
||||
(buf[i + 2] & 0xc0) !== 0x80 ||
|
||||
(buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong
|
||||
(buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i += 3;
|
||||
} else if ((buf[i] & 0xf8) === 0xf0) {
|
||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
if (
|
||||
i + 3 >= len ||
|
||||
(buf[i + 1] & 0xc0) !== 0x80 ||
|
||||
(buf[i + 2] & 0xc0) !== 0x80 ||
|
||||
(buf[i + 3] & 0xc0) !== 0x80 ||
|
||||
(buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong
|
||||
(buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||
|
||||
buf[i] > 0xf4 // > U+10FFFF
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i += 4;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
let isValidUTF8 = require('utf-8-validate');
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (typeof isValidUTF8 === 'object') {
|
||||
isValidUTF8 = isValidUTF8.Validation.isValidUTF8; // utf-8-validate@<3.0.0
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isValidStatusCode,
|
||||
isValidUTF8(buf) {
|
||||
return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
||||
}
|
||||
};
|
||||
} catch (e) /* istanbul ignore next */ {
|
||||
module.exports = {
|
||||
isValidStatusCode,
|
||||
isValidUTF8: _isValidUTF8
|
||||
};
|
||||
}
|
||||
447
WebUI/node_modules/mqtt/node_modules/ws/lib/websocket-server.js
generated
vendored
Normal file
447
WebUI/node_modules/mqtt/node_modules/ws/lib/websocket-server.js
generated
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls|https$" }] */
|
||||
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const { createHash } = require('crypto');
|
||||
|
||||
const PerMessageDeflate = require('./permessage-deflate');
|
||||
const WebSocket = require('./websocket');
|
||||
const { format, parse } = require('./extension');
|
||||
const { GUID, kWebSocket } = require('./constants');
|
||||
|
||||
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
||||
|
||||
const RUNNING = 0;
|
||||
const CLOSING = 1;
|
||||
const CLOSED = 2;
|
||||
|
||||
/**
|
||||
* Class representing a WebSocket server.
|
||||
*
|
||||
* @extends EventEmitter
|
||||
*/
|
||||
class WebSocketServer extends EventEmitter {
|
||||
/**
|
||||
* Create a `WebSocketServer` instance.
|
||||
*
|
||||
* @param {Object} options Configuration options
|
||||
* @param {Number} [options.backlog=511] The maximum length of the queue of
|
||||
* pending connections
|
||||
* @param {Boolean} [options.clientTracking=true] Specifies whether or not to
|
||||
* track clients
|
||||
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
||||
* @param {String} [options.host] The hostname where to bind the server
|
||||
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
||||
* size
|
||||
* @param {Boolean} [options.noServer=false] Enable no server mode
|
||||
* @param {String} [options.path] Accept only connections matching this path
|
||||
* @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
|
||||
* permessage-deflate
|
||||
* @param {Number} [options.port] The port where to bind the server
|
||||
* @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
|
||||
* server to use
|
||||
* @param {Function} [options.verifyClient] A hook to reject connections
|
||||
* @param {Function} [callback] A listener for the `listening` event
|
||||
*/
|
||||
constructor(options, callback) {
|
||||
super();
|
||||
|
||||
options = {
|
||||
maxPayload: 100 * 1024 * 1024,
|
||||
perMessageDeflate: false,
|
||||
handleProtocols: null,
|
||||
clientTracking: true,
|
||||
verifyClient: null,
|
||||
noServer: false,
|
||||
backlog: null, // use default (511 as implemented in net.js)
|
||||
server: null,
|
||||
host: null,
|
||||
path: null,
|
||||
port: null,
|
||||
...options
|
||||
};
|
||||
|
||||
if (
|
||||
(options.port == null && !options.server && !options.noServer) ||
|
||||
(options.port != null && (options.server || options.noServer)) ||
|
||||
(options.server && options.noServer)
|
||||
) {
|
||||
throw new TypeError(
|
||||
'One and only one of the "port", "server", or "noServer" options ' +
|
||||
'must be specified'
|
||||
);
|
||||
}
|
||||
|
||||
if (options.port != null) {
|
||||
this._server = http.createServer((req, res) => {
|
||||
const body = http.STATUS_CODES[426];
|
||||
|
||||
res.writeHead(426, {
|
||||
'Content-Length': body.length,
|
||||
'Content-Type': 'text/plain'
|
||||
});
|
||||
res.end(body);
|
||||
});
|
||||
this._server.listen(
|
||||
options.port,
|
||||
options.host,
|
||||
options.backlog,
|
||||
callback
|
||||
);
|
||||
} else if (options.server) {
|
||||
this._server = options.server;
|
||||
}
|
||||
|
||||
if (this._server) {
|
||||
const emitConnection = this.emit.bind(this, 'connection');
|
||||
|
||||
this._removeListeners = addListeners(this._server, {
|
||||
listening: this.emit.bind(this, 'listening'),
|
||||
error: this.emit.bind(this, 'error'),
|
||||
upgrade: (req, socket, head) => {
|
||||
this.handleUpgrade(req, socket, head, emitConnection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
|
||||
if (options.clientTracking) this.clients = new Set();
|
||||
this.options = options;
|
||||
this._state = RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bound address, the address family name, and port of the server
|
||||
* as reported by the operating system if listening on an IP socket.
|
||||
* If the server is listening on a pipe or UNIX domain socket, the name is
|
||||
* returned as a string.
|
||||
*
|
||||
* @return {(Object|String|null)} The address of the server
|
||||
* @public
|
||||
*/
|
||||
address() {
|
||||
if (this.options.noServer) {
|
||||
throw new Error('The server is operating in "noServer" mode');
|
||||
}
|
||||
|
||||
if (!this._server) return null;
|
||||
return this._server.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the server.
|
||||
*
|
||||
* @param {Function} [cb] Callback
|
||||
* @public
|
||||
*/
|
||||
close(cb) {
|
||||
if (cb) this.once('close', cb);
|
||||
|
||||
if (this._state === CLOSED) {
|
||||
process.nextTick(emitClose, this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._state === CLOSING) return;
|
||||
this._state = CLOSING;
|
||||
|
||||
//
|
||||
// Terminate all associated clients.
|
||||
//
|
||||
if (this.clients) {
|
||||
for (const client of this.clients) client.terminate();
|
||||
}
|
||||
|
||||
const server = this._server;
|
||||
|
||||
if (server) {
|
||||
this._removeListeners();
|
||||
this._removeListeners = this._server = null;
|
||||
|
||||
//
|
||||
// Close the http server if it was internally created.
|
||||
//
|
||||
if (this.options.port != null) {
|
||||
server.close(emitClose.bind(undefined, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
process.nextTick(emitClose, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a given request should be handled by this server instance.
|
||||
*
|
||||
* @param {http.IncomingMessage} req Request object to inspect
|
||||
* @return {Boolean} `true` if the request is valid, else `false`
|
||||
* @public
|
||||
*/
|
||||
shouldHandle(req) {
|
||||
if (this.options.path) {
|
||||
const index = req.url.indexOf('?');
|
||||
const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
|
||||
|
||||
if (pathname !== this.options.path) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a HTTP Upgrade request.
|
||||
*
|
||||
* @param {http.IncomingMessage} req The request object
|
||||
* @param {(net.Socket|tls.Socket)} socket The network socket between the
|
||||
* server and client
|
||||
* @param {Buffer} head The first packet of the upgraded stream
|
||||
* @param {Function} cb Callback
|
||||
* @public
|
||||
*/
|
||||
handleUpgrade(req, socket, head, cb) {
|
||||
socket.on('error', socketOnError);
|
||||
|
||||
const key =
|
||||
req.headers['sec-websocket-key'] !== undefined
|
||||
? req.headers['sec-websocket-key'].trim()
|
||||
: false;
|
||||
const version = +req.headers['sec-websocket-version'];
|
||||
const extensions = {};
|
||||
|
||||
if (
|
||||
req.method !== 'GET' ||
|
||||
req.headers.upgrade.toLowerCase() !== 'websocket' ||
|
||||
!key ||
|
||||
!keyRegex.test(key) ||
|
||||
(version !== 8 && version !== 13) ||
|
||||
!this.shouldHandle(req)
|
||||
) {
|
||||
return abortHandshake(socket, 400);
|
||||
}
|
||||
|
||||
if (this.options.perMessageDeflate) {
|
||||
const perMessageDeflate = new PerMessageDeflate(
|
||||
this.options.perMessageDeflate,
|
||||
true,
|
||||
this.options.maxPayload
|
||||
);
|
||||
|
||||
try {
|
||||
const offers = parse(req.headers['sec-websocket-extensions']);
|
||||
|
||||
if (offers[PerMessageDeflate.extensionName]) {
|
||||
perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
|
||||
extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
|
||||
}
|
||||
} catch (err) {
|
||||
return abortHandshake(socket, 400);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Optionally call external client verification handler.
|
||||
//
|
||||
if (this.options.verifyClient) {
|
||||
const info = {
|
||||
origin:
|
||||
req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],
|
||||
secure: !!(req.socket.authorized || req.socket.encrypted),
|
||||
req
|
||||
};
|
||||
|
||||
if (this.options.verifyClient.length === 2) {
|
||||
this.options.verifyClient(info, (verified, code, message, headers) => {
|
||||
if (!verified) {
|
||||
return abortHandshake(socket, code || 401, message, headers);
|
||||
}
|
||||
|
||||
this.completeUpgrade(key, extensions, req, socket, head, cb);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
|
||||
}
|
||||
|
||||
this.completeUpgrade(key, extensions, req, socket, head, cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade the connection to WebSocket.
|
||||
*
|
||||
* @param {String} key The value of the `Sec-WebSocket-Key` header
|
||||
* @param {Object} extensions The accepted extensions
|
||||
* @param {http.IncomingMessage} req The request object
|
||||
* @param {(net.Socket|tls.Socket)} socket The network socket between the
|
||||
* server and client
|
||||
* @param {Buffer} head The first packet of the upgraded stream
|
||||
* @param {Function} cb Callback
|
||||
* @throws {Error} If called more than once with the same socket
|
||||
* @private
|
||||
*/
|
||||
completeUpgrade(key, extensions, req, socket, head, cb) {
|
||||
//
|
||||
// Destroy the socket if the client has already sent a FIN packet.
|
||||
//
|
||||
if (!socket.readable || !socket.writable) return socket.destroy();
|
||||
|
||||
if (socket[kWebSocket]) {
|
||||
throw new Error(
|
||||
'server.handleUpgrade() was called more than once with the same ' +
|
||||
'socket, possibly due to a misconfiguration'
|
||||
);
|
||||
}
|
||||
|
||||
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
||||
|
||||
const digest = createHash('sha1')
|
||||
.update(key + GUID)
|
||||
.digest('base64');
|
||||
|
||||
const headers = [
|
||||
'HTTP/1.1 101 Switching Protocols',
|
||||
'Upgrade: websocket',
|
||||
'Connection: Upgrade',
|
||||
`Sec-WebSocket-Accept: ${digest}`
|
||||
];
|
||||
|
||||
const ws = new WebSocket(null);
|
||||
let protocol = req.headers['sec-websocket-protocol'];
|
||||
|
||||
if (protocol) {
|
||||
protocol = protocol.split(',').map(trim);
|
||||
|
||||
//
|
||||
// Optionally call external protocol selection handler.
|
||||
//
|
||||
if (this.options.handleProtocols) {
|
||||
protocol = this.options.handleProtocols(protocol, req);
|
||||
} else {
|
||||
protocol = protocol[0];
|
||||
}
|
||||
|
||||
if (protocol) {
|
||||
headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
|
||||
ws._protocol = protocol;
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions[PerMessageDeflate.extensionName]) {
|
||||
const params = extensions[PerMessageDeflate.extensionName].params;
|
||||
const value = format({
|
||||
[PerMessageDeflate.extensionName]: [params]
|
||||
});
|
||||
headers.push(`Sec-WebSocket-Extensions: ${value}`);
|
||||
ws._extensions = extensions;
|
||||
}
|
||||
|
||||
//
|
||||
// Allow external modification/inspection of handshake headers.
|
||||
//
|
||||
this.emit('headers', headers, req);
|
||||
|
||||
socket.write(headers.concat('\r\n').join('\r\n'));
|
||||
socket.removeListener('error', socketOnError);
|
||||
|
||||
ws.setSocket(socket, head, this.options.maxPayload);
|
||||
|
||||
if (this.clients) {
|
||||
this.clients.add(ws);
|
||||
ws.on('close', () => this.clients.delete(ws));
|
||||
}
|
||||
|
||||
cb(ws, req);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebSocketServer;
|
||||
|
||||
/**
|
||||
* Add event listeners on an `EventEmitter` using a map of <event, listener>
|
||||
* pairs.
|
||||
*
|
||||
* @param {EventEmitter} server The event emitter
|
||||
* @param {Object.<String, Function>} map The listeners to add
|
||||
* @return {Function} A function that will remove the added listeners when
|
||||
* called
|
||||
* @private
|
||||
*/
|
||||
function addListeners(server, map) {
|
||||
for (const event of Object.keys(map)) server.on(event, map[event]);
|
||||
|
||||
return function removeListeners() {
|
||||
for (const event of Object.keys(map)) {
|
||||
server.removeListener(event, map[event]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a `'close'` event on an `EventEmitter`.
|
||||
*
|
||||
* @param {EventEmitter} server The event emitter
|
||||
* @private
|
||||
*/
|
||||
function emitClose(server) {
|
||||
server._state = CLOSED;
|
||||
server.emit('close');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle premature socket errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function socketOnError() {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection when preconditions are not fulfilled.
|
||||
*
|
||||
* @param {(net.Socket|tls.Socket)} socket The socket of the upgrade request
|
||||
* @param {Number} code The HTTP response status code
|
||||
* @param {String} [message] The HTTP response body
|
||||
* @param {Object} [headers] Additional HTTP response headers
|
||||
* @private
|
||||
*/
|
||||
function abortHandshake(socket, code, message, headers) {
|
||||
if (socket.writable) {
|
||||
message = message || http.STATUS_CODES[code];
|
||||
headers = {
|
||||
Connection: 'close',
|
||||
'Content-Type': 'text/html',
|
||||
'Content-Length': Buffer.byteLength(message),
|
||||
...headers
|
||||
};
|
||||
|
||||
socket.write(
|
||||
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
|
||||
Object.keys(headers)
|
||||
.map((h) => `${h}: ${headers[h]}`)
|
||||
.join('\r\n') +
|
||||
'\r\n\r\n' +
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
socket.removeListener('error', socketOnError);
|
||||
socket.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove whitespace characters from both ends of a string.
|
||||
*
|
||||
* @param {String} str The string
|
||||
* @return {String} A new string representing `str` stripped of whitespace
|
||||
* characters from both its beginning and end
|
||||
* @private
|
||||
*/
|
||||
function trim(str) {
|
||||
return str.trim();
|
||||
}
|
||||
1195
WebUI/node_modules/mqtt/node_modules/ws/lib/websocket.js
generated
vendored
Normal file
1195
WebUI/node_modules/mqtt/node_modules/ws/lib/websocket.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
56
WebUI/node_modules/mqtt/node_modules/ws/package.json
generated
vendored
Normal file
56
WebUI/node_modules/mqtt/node_modules/ws/package.json
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "ws",
|
||||
"version": "7.5.9",
|
||||
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
|
||||
"keywords": [
|
||||
"HyBi",
|
||||
"Push",
|
||||
"RFC-6455",
|
||||
"WebSocket",
|
||||
"WebSockets",
|
||||
"real-time"
|
||||
],
|
||||
"homepage": "https://github.com/websockets/ws",
|
||||
"bugs": "https://github.com/websockets/ws/issues",
|
||||
"repository": "websockets/ws",
|
||||
"author": "Einar Otto Stangvik <einaros@gmail.com> (http://2x.io)",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"browser": "browser.js",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"files": [
|
||||
"browser.js",
|
||||
"index.js",
|
||||
"lib/*.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js",
|
||||
"integration": "mocha --throw-deprecation test/*.integration.js",
|
||||
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\""
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"benchmark": "^2.1.4",
|
||||
"bufferutil": "^4.0.1",
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"mocha": "^7.0.0",
|
||||
"nyc": "^15.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
}
|
||||
}
|
||||
113
WebUI/node_modules/mqtt/package.json
generated
vendored
Normal file
113
WebUI/node_modules/mqtt/package.json
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"name": "mqtt",
|
||||
"description": "A library for the MQTT protocol",
|
||||
"version": "4.3.7",
|
||||
"contributors": [
|
||||
"Adam Rudd <adamvrr@gmail.com>",
|
||||
"Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
|
||||
"Siarhei Buntsevich <scarry0506@gmail.com> (https://github.com/scarry1992)",
|
||||
"Yoseph Maguire <yomaguir@microsoft.com> (https://github.com/YoDaMa)"
|
||||
],
|
||||
"keywords": [
|
||||
"mqtt",
|
||||
"publish/subscribe",
|
||||
"publish",
|
||||
"subscribe"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/mqttjs/MQTT.js.git"
|
||||
},
|
||||
"main": "mqtt.js",
|
||||
"types": "types/index.d.ts",
|
||||
"scripts": {
|
||||
"pretest": "standard | snazzy",
|
||||
"typescript-compile-test": "tsc -p test/typescript/tsconfig.json",
|
||||
"typescript-compile-execute": "node test/typescript/broker-connect-subscribe-and-publish.js",
|
||||
"browser-build": "rimraf dist/ && mkdirp dist/ && browserify mqtt.js --standalone mqtt > dist/mqtt.js && uglifyjs dist/mqtt.js --compress --mangle --output dist/mqtt.min.js",
|
||||
"prepare": "npm run browser-build",
|
||||
"unit-test:node": "node_modules/.bin/nyc --reporter=lcov --reporter=text ./node_modules/mocha/bin/_mocha --exit",
|
||||
"unit-test:browser": "airtap --server test/browser/server.js test/browser/test.js",
|
||||
"test:node": "npm run unit-test:node && codecov",
|
||||
"test:browser": "npm run browser-build && npm run unit-test:browser",
|
||||
"test:typescript": "npm run typescript-compile-test && npm run typescript-compile-execute",
|
||||
"test": "npm run test:node && npm run test:typescript"
|
||||
},
|
||||
"pre-commit": [
|
||||
"pretest"
|
||||
],
|
||||
"bin": {
|
||||
"mqtt_pub": "./bin/pub.js",
|
||||
"mqtt_sub": "./bin/sub.js",
|
||||
"mqtt": "./bin/mqtt.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"CONTRIBUTING.md",
|
||||
"doc",
|
||||
"lib",
|
||||
"bin",
|
||||
"types",
|
||||
"mqtt.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"browser": {
|
||||
"./mqtt.js": "./lib/connect/index.js",
|
||||
"fs": false,
|
||||
"tls": false,
|
||||
"net": false
|
||||
},
|
||||
"dependencies": {
|
||||
"commist": "^1.0.0",
|
||||
"concat-stream": "^2.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"duplexify": "^4.1.1",
|
||||
"help-me": "^3.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"lru-cache": "^6.0.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mqtt-packet": "^6.8.0",
|
||||
"number-allocator": "^1.0.9",
|
||||
"pump": "^3.0.0",
|
||||
"readable-stream": "^3.6.0",
|
||||
"reinterval": "^1.1.0",
|
||||
"rfdc": "^1.3.0",
|
||||
"split2": "^3.1.0",
|
||||
"ws": "^7.5.5",
|
||||
"xtend": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^10.0.0",
|
||||
"@types/tape": "^4.13.2",
|
||||
"@types/ws": "^7.4.7",
|
||||
"aedes": "^0.46.2",
|
||||
"airtap": "^4.0.4",
|
||||
"browserify": "^16.5.0",
|
||||
"chai": "^4.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"codecov": "^3.0.4",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"global": "^4.3.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^9.2.0",
|
||||
"mqtt-connection": "^4.0.0",
|
||||
"nyc": "^15.0.1",
|
||||
"pre-commit": "^1.2.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"should": "^13.2.1",
|
||||
"sinon": "^9.0.0",
|
||||
"snazzy": "^9.0.0",
|
||||
"standard": "^16.0.4",
|
||||
"tape": "^5.5.2",
|
||||
"typescript": "^4.5.5",
|
||||
"uglify-es": "^3.3.9"
|
||||
},
|
||||
"standard": {
|
||||
"env": [
|
||||
"mocha"
|
||||
]
|
||||
}
|
||||
}
|
||||
30
WebUI/node_modules/mqtt/types/index.d.ts
generated
vendored
Normal file
30
WebUI/node_modules/mqtt/types/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
export * from './lib/client'
|
||||
export * from './lib/connect'
|
||||
export * from './lib/store'
|
||||
export * from './lib/client-options'
|
||||
import { MqttClient } from './lib/client'
|
||||
export { MqttClient as Client }
|
||||
export {
|
||||
QoS,
|
||||
PacketCmd,
|
||||
IPacket,
|
||||
IConnectPacket,
|
||||
IPublishPacket,
|
||||
IConnackPacket,
|
||||
ISubscription,
|
||||
ISubscribePacket,
|
||||
ISubackPacket,
|
||||
IUnsubscribePacket,
|
||||
IUnsubackPacket,
|
||||
IPubackPacket,
|
||||
IPubcompPacket,
|
||||
IPubrelPacket,
|
||||
IPubrecPacket,
|
||||
IPingreqPacket,
|
||||
IPingrespPacket,
|
||||
IDisconnectPacket,
|
||||
Packet,
|
||||
UserProperties
|
||||
} from 'mqtt-packet'
|
||||
export { IMessageIdProvider } from './lib/message-id-provider'
|
||||
export { UniqueMessageIdProvider } from './lib/unique-message-id-provider'
|
||||
204
WebUI/node_modules/mqtt/types/lib/client-options.d.ts
generated
vendored
Normal file
204
WebUI/node_modules/mqtt/types/lib/client-options.d.ts
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
import { MqttClient } from './client'
|
||||
import { Store } from './store'
|
||||
import { ClientOptions } from 'ws'
|
||||
import { ClientRequestArgs } from 'http'
|
||||
import { QoS, UserProperties } from 'mqtt-packet'
|
||||
import { IMessageIdProvider } from './message-id-provider'
|
||||
|
||||
export declare type StorePutCallback = () => void
|
||||
|
||||
export interface IClientOptions extends ISecureClientOptions {
|
||||
port?: number // port is made into a number subsequently
|
||||
host?: string // host does NOT include port
|
||||
hostname?: string
|
||||
path?: string
|
||||
protocol?: 'wss' | 'ws' | 'mqtt' | 'mqtts' | 'tcp' | 'ssl' | 'wx' | 'wxs'
|
||||
|
||||
wsOptions?: ClientOptions | ClientRequestArgs
|
||||
/**
|
||||
* 10 seconds, set to 0 to disable
|
||||
*/
|
||||
keepalive?: number
|
||||
/**
|
||||
* 'mqttjs_' + Math.random().toString(16).substr(2, 8)
|
||||
*/
|
||||
clientId?: string
|
||||
/**
|
||||
* 'MQTT'
|
||||
*/
|
||||
protocolId?: string
|
||||
/**
|
||||
* 4
|
||||
*/
|
||||
protocolVersion?: number
|
||||
/**
|
||||
* true, set to false to receive QoS 1 and 2 messages while offline
|
||||
*/
|
||||
clean?: boolean
|
||||
/**
|
||||
* 1000 milliseconds, interval between two reconnections
|
||||
*/
|
||||
reconnectPeriod?: number
|
||||
/**
|
||||
* 30 * 1000 milliseconds, time to wait before a CONNACK is received
|
||||
*/
|
||||
connectTimeout?: number
|
||||
/**
|
||||
* the username required by your broker, if any
|
||||
*/
|
||||
username?: string
|
||||
/**
|
||||
* the password required by your broker, if any
|
||||
*/
|
||||
password?: string
|
||||
/**
|
||||
* a Store for the incoming packets
|
||||
*/
|
||||
incomingStore?: Store
|
||||
/**
|
||||
* a Store for the outgoing packets
|
||||
*/
|
||||
outgoingStore?: Store
|
||||
queueQoSZero?: boolean
|
||||
reschedulePings?: boolean
|
||||
servers?: Array<{
|
||||
host: string
|
||||
port: number
|
||||
protocol?: 'wss' | 'ws' | 'mqtt' | 'mqtts' | 'tcp' | 'ssl' | 'wx' | 'wxs'
|
||||
}>
|
||||
/**
|
||||
* true, set to false to disable re-subscribe functionality
|
||||
*/
|
||||
resubscribe?: boolean
|
||||
/**
|
||||
* a message that will sent by the broker automatically when the client disconnect badly.
|
||||
*/
|
||||
will?: {
|
||||
/**
|
||||
* the topic to publish
|
||||
*/
|
||||
topic: string
|
||||
/**
|
||||
* the message to publish
|
||||
*/
|
||||
payload: Buffer | string
|
||||
/**
|
||||
* the QoS
|
||||
*/
|
||||
qos: QoS
|
||||
/**
|
||||
* the retain flag
|
||||
*/
|
||||
retain: boolean,
|
||||
/*
|
||||
* properies object of will
|
||||
* */
|
||||
properties?: {
|
||||
willDelayInterval?: number,
|
||||
payloadFormatIndicator?: boolean,
|
||||
messageExpiryInterval?: number,
|
||||
contentType?: string,
|
||||
responseTopic?: string,
|
||||
correlationData?: Buffer,
|
||||
userProperties?: UserProperties
|
||||
}
|
||||
}
|
||||
transformWsUrl?: (url: string, options: IClientOptions, client: MqttClient) => string,
|
||||
properties?: {
|
||||
sessionExpiryInterval?: number,
|
||||
receiveMaximum?: number,
|
||||
maximumPacketSize?: number,
|
||||
topicAliasMaximum?: number,
|
||||
requestResponseInformation?: boolean,
|
||||
requestProblemInformation?: boolean,
|
||||
userProperties?: UserProperties,
|
||||
authenticationMethod?: string,
|
||||
authenticationData?: Buffer
|
||||
},
|
||||
messageIdProvider?: IMessageIdProvider
|
||||
}
|
||||
export interface ISecureClientOptions {
|
||||
/**
|
||||
* optional private keys in PEM format
|
||||
*/
|
||||
key?: string | string[] | Buffer | Buffer[] | Object[]
|
||||
/**
|
||||
* optional cert chains in PEM format
|
||||
*/
|
||||
cert?: string | string[] | Buffer | Buffer[]
|
||||
/**
|
||||
* Optionally override the trusted CA certificates in PEM format
|
||||
*/
|
||||
ca?: string | string[] | Buffer | Buffer[]
|
||||
rejectUnauthorized?: boolean
|
||||
/**
|
||||
* optional alpn's
|
||||
*/
|
||||
ALPNProtocols?: string[] | Buffer[] | Uint8Array[] | Buffer | Uint8Array
|
||||
}
|
||||
export interface IClientPublishOptions {
|
||||
/**
|
||||
* the QoS
|
||||
*/
|
||||
qos?: QoS
|
||||
/**
|
||||
* the retain flag
|
||||
*/
|
||||
retain?: boolean
|
||||
/**
|
||||
* whether or not mark a message as duplicate
|
||||
*/
|
||||
dup?: boolean
|
||||
/*
|
||||
* MQTT 5.0 properties object
|
||||
*/
|
||||
properties?: {
|
||||
payloadFormatIndicator?: boolean,
|
||||
messageExpiryInterval?: number,
|
||||
topicAlias?: number,
|
||||
responseTopic?: string,
|
||||
correlationData?: Buffer,
|
||||
userProperties?: UserProperties,
|
||||
subscriptionIdentifier?: number,
|
||||
contentType?: string
|
||||
}
|
||||
/**
|
||||
* callback called when message is put into `outgoingStore`
|
||||
*/
|
||||
cbStorePut?: StorePutCallback
|
||||
}
|
||||
export interface IClientSubscribeOptions {
|
||||
/**
|
||||
* the QoS
|
||||
*/
|
||||
qos: QoS,
|
||||
/*
|
||||
* no local flag
|
||||
* */
|
||||
nl?: boolean,
|
||||
/*
|
||||
* Retain As Published flag
|
||||
* */
|
||||
rap?: boolean,
|
||||
/*
|
||||
* Retain Handling option
|
||||
* */
|
||||
rh?: number,
|
||||
/*
|
||||
* MQTT 5.0 properies object of subscribe
|
||||
* */
|
||||
properties?: {
|
||||
subscriptionIdentifier?: number,
|
||||
userProperties?: UserProperties
|
||||
}
|
||||
}
|
||||
export interface IClientReconnectOptions {
|
||||
/**
|
||||
* a Store for the incoming packets
|
||||
*/
|
||||
incomingStore?: Store
|
||||
/**
|
||||
* a Store for the outgoing packets
|
||||
*/
|
||||
outgoingStore?: Store
|
||||
}
|
||||
261
WebUI/node_modules/mqtt/types/lib/client.d.ts
generated
vendored
Normal file
261
WebUI/node_modules/mqtt/types/lib/client.d.ts
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import * as events from 'events'
|
||||
import {
|
||||
IClientOptions,
|
||||
IClientPublishOptions,
|
||||
IClientSubscribeOptions,
|
||||
IClientReconnectOptions
|
||||
} from './client-options'
|
||||
import { Store } from './store'
|
||||
import { IAuthPacket, IConnectPacket, IPublishPacket, IDisconnectPacket, IConnackPacket, Packet, QoS } from 'mqtt-packet'
|
||||
|
||||
export interface ISubscriptionGrant {
|
||||
/**
|
||||
* is a subscribed to topic
|
||||
*/
|
||||
topic: string
|
||||
/**
|
||||
* is the granted qos level on it, may return 128 on error
|
||||
*/
|
||||
qos: QoS | number
|
||||
/*
|
||||
* no local flag
|
||||
* */
|
||||
nl?: boolean,
|
||||
/*
|
||||
* Retain As Published flag
|
||||
* */
|
||||
rap?: boolean,
|
||||
/*
|
||||
* Retain Handling option
|
||||
* */
|
||||
rh?: number
|
||||
}
|
||||
export interface ISubscriptionRequest {
|
||||
/**
|
||||
* is a subscribed to topic
|
||||
*/
|
||||
topic: string
|
||||
/**
|
||||
* is the granted qos level on it
|
||||
*/
|
||||
qos: QoS
|
||||
/*
|
||||
* no local flag
|
||||
* */
|
||||
nl?: boolean,
|
||||
/*
|
||||
* Retain As Published flag
|
||||
* */
|
||||
rap?: boolean,
|
||||
/*
|
||||
* Retain Handling option
|
||||
* */
|
||||
rh?: number
|
||||
}
|
||||
export interface ISubscriptionMap {
|
||||
/**
|
||||
* object which has topic names as object keys and as value the options, like {'test1': {qos: 0}, 'test2': {qos: 2}}.
|
||||
*/
|
||||
[topic: string]: {
|
||||
qos: QoS,
|
||||
nl?: boolean,
|
||||
rap?: boolean,
|
||||
rh?: number
|
||||
}
|
||||
}
|
||||
|
||||
export declare type OnConnectCallback = (packet: IConnackPacket) => void
|
||||
export declare type OnDisconnectCallback = (packet: IDisconnectPacket) => void
|
||||
export declare type ClientSubscribeCallback = (err: Error, granted: ISubscriptionGrant[]) => void
|
||||
export declare type OnMessageCallback = (topic: string, payload: Buffer, packet: IPublishPacket) => void
|
||||
export declare type OnPacketCallback = (packet: Packet) => void
|
||||
export declare type OnCloseCallback = () => void
|
||||
export declare type OnErrorCallback = (error: Error) => void
|
||||
export declare type PacketCallback = (error?: Error, packet?: Packet) => any
|
||||
export declare type CloseCallback = (error?: Error) => void
|
||||
|
||||
export interface IStream extends events.EventEmitter {
|
||||
pipe (to: any): any
|
||||
destroy (): any
|
||||
end (): any
|
||||
}
|
||||
/**
|
||||
* MqttClient constructor
|
||||
*
|
||||
* @param {Stream} stream - stream
|
||||
* @param {Object} [options] - connection options
|
||||
* (see Connection#connect)
|
||||
*/
|
||||
export declare class MqttClient extends events.EventEmitter {
|
||||
public connected: boolean
|
||||
public disconnecting: boolean
|
||||
public disconnected: boolean
|
||||
public reconnecting: boolean
|
||||
public incomingStore: Store
|
||||
public outgoingStore: Store
|
||||
public options: IClientOptions
|
||||
public queueQoSZero: boolean
|
||||
|
||||
constructor (streamBuilder: (client: MqttClient) => IStream, options: IClientOptions)
|
||||
|
||||
public on (event: 'connect', cb: OnConnectCallback): this
|
||||
public on (event: 'message', cb: OnMessageCallback): this
|
||||
public on (event: 'packetsend' | 'packetreceive', cb: OnPacketCallback): this
|
||||
public on (event: 'disconnect', cb: OnDisconnectCallback): this
|
||||
public on (event: 'error', cb: OnErrorCallback): this
|
||||
public on (event: 'close', cb: OnCloseCallback): this
|
||||
public on (event: 'end' | 'reconnect' | 'offline' | 'outgoingEmpty', cb: () => void): this
|
||||
public on (event: string, cb: Function): this
|
||||
|
||||
public once (event: 'connect', cb: OnConnectCallback): this
|
||||
public once (event: 'message', cb: OnMessageCallback): this
|
||||
public once (event: 'packetsend' | 'packetreceive', cb: OnPacketCallback): this
|
||||
public once (event: 'disconnect', cb: OnDisconnectCallback): this
|
||||
public once (event: 'error', cb: OnErrorCallback): this
|
||||
public once (event: 'close', cb: OnCloseCallback): this
|
||||
public once (event: 'end' | 'reconnect' | 'offline' | 'outgoingEmpty', cb: () => void): this
|
||||
public once (event: string, cb: Function): this
|
||||
|
||||
/**
|
||||
* publish - publish <message> to <topic>
|
||||
*
|
||||
* @param {String} topic - topic to publish to
|
||||
* @param {(String|Buffer)} message - message to publish
|
||||
*
|
||||
* @param {Object} [opts] - publish options, includes:
|
||||
* @param {Number} [opts.qos] - qos level to publish on
|
||||
* @param {Boolean} [opts.retain] - whether or not to retain the message
|
||||
* @param {Function}[opts.cbStorePut] - function(){}
|
||||
* called when message is put into `outgoingStore`
|
||||
*
|
||||
* @param {Function} [callback] - function(err){}
|
||||
* called when publish succeeds or fails
|
||||
*
|
||||
* @returns {Client} this - for chaining
|
||||
* @api public
|
||||
*
|
||||
* @example client.publish('topic', 'message')
|
||||
* @example
|
||||
* client.publish('topic', 'message', {qos: 1, retain: true})
|
||||
* @example client.publish('topic', 'message', console.log)
|
||||
*/
|
||||
public publish (topic: string, message: string | Buffer,
|
||||
opts: IClientPublishOptions, callback?: PacketCallback): this
|
||||
public publish (topic: string, message: string | Buffer,
|
||||
callback?: PacketCallback): this
|
||||
|
||||
/**
|
||||
* subscribe - subscribe to <topic>
|
||||
*
|
||||
* @param {String, Array, Object} topic - topic(s) to subscribe to, supports objects in the form {'topic': qos}
|
||||
* @param {Object} [opts] - optional subscription options, includes:
|
||||
* @param {Number} [opts.qos] - subscribe qos level
|
||||
* @param {Function} [callback] - function(err, granted){} where:
|
||||
* {Error} err - subscription error (none at the moment!)
|
||||
* {Array} granted - array of {topic: 't', qos: 0}
|
||||
* @returns {MqttClient} this - for chaining
|
||||
* @api public
|
||||
* @example client.subscribe('topic')
|
||||
* @example client.subscribe('topic', {qos: 1})
|
||||
* @example client.subscribe({'topic': 0, 'topic2': 1}, console.log)
|
||||
* @example client.subscribe('topic', console.log)
|
||||
*/
|
||||
public subscribe (topic:
|
||||
string
|
||||
| string[], opts: IClientSubscribeOptions, callback?: ClientSubscribeCallback): this
|
||||
public subscribe (topic:
|
||||
string
|
||||
| string[]
|
||||
| ISubscriptionMap, callback?: ClientSubscribeCallback): this
|
||||
|
||||
/**
|
||||
* unsubscribe - unsubscribe from topic(s)
|
||||
*
|
||||
* @param {String, Array} topic - topics to unsubscribe from
|
||||
* @param {Object} opts - opts of unsubscribe
|
||||
* @param {Function} [callback] - callback fired on unsuback
|
||||
* @returns {MqttClient} this - for chaining
|
||||
* @api public
|
||||
* @example client.unsubscribe('topic')
|
||||
* @example client.unsubscribe('topic', console.log)
|
||||
* @example client.unsubscribe('topic', opts, console.log)
|
||||
*/
|
||||
public unsubscribe (topic: string | string[], opts?: Object, callback?: PacketCallback): this
|
||||
|
||||
/**
|
||||
* end - close connection
|
||||
*
|
||||
* @returns {MqttClient} this - for chaining
|
||||
* @param {Boolean} force - do not wait for all in-flight messages to be acked
|
||||
* @param {Object} opts - opts disconnect
|
||||
* @param {Function} cb - called when the client has been closed
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
public end (force?: boolean, opts?: Object, cb?: CloseCallback): this
|
||||
|
||||
/**
|
||||
* removeOutgoingMessage - remove a message in outgoing store
|
||||
* the outgoing callback will be called withe Error('Message removed') if the message is removed
|
||||
*
|
||||
* @param {Number} mid - messageId to remove message
|
||||
* @returns {MqttClient} this - for chaining
|
||||
* @api public
|
||||
*
|
||||
* @example client.removeOutgoingMessage(client.getLastMessageId());
|
||||
*/
|
||||
public removeOutgoingMessage (mid: number): this
|
||||
|
||||
/**
|
||||
* reconnect - connect again using the same options as connect()
|
||||
*
|
||||
* @param {Object} [opts] - optional reconnect options, includes:
|
||||
* {Store} incomingStore - a store for the incoming packets
|
||||
* {Store} outgoingStore - a store for the outgoing packets
|
||||
* if opts is not given, current stores are used
|
||||
*
|
||||
* @returns {MqttClient} this - for chaining
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
public reconnect (opts?: IClientReconnectOptions): this
|
||||
|
||||
/**
|
||||
* Handle messages with backpressure support, one at a time.
|
||||
* Override at will.
|
||||
*
|
||||
* @param packet packet the packet
|
||||
* @param callback callback call when finished
|
||||
* @api public
|
||||
*/
|
||||
public handleMessage (packet: Packet, callback: PacketCallback): void
|
||||
|
||||
/**
|
||||
* Handle auth packages for MQTT 5 enhanced authentication methods such
|
||||
* as challenge response authentication.
|
||||
*
|
||||
* Challenge-response authentication flow would look something like this:
|
||||
*
|
||||
* --> CONNECT | authMethod = "mathChallenge" -->
|
||||
* <-- AUTH | authMethod = "mathChallenge", authData = "12 + 34" <--
|
||||
* --> AUTH | authMethod = "mathChallenge", authData = "46" -->
|
||||
* <-- CONNACK | reasonCode = SUCCESS <--
|
||||
*
|
||||
* This form of authentication has several advantages over traditional
|
||||
* credential-based approaches. For instance authentication without the direct
|
||||
* exchange of authentication secrets.
|
||||
*
|
||||
* @param packet the auth packet to handle
|
||||
* @param callback call when finished
|
||||
* @api public
|
||||
*/
|
||||
public handleAuth (packet: IAuthPacket, callback: PacketCallback): void
|
||||
|
||||
/**
|
||||
* getLastMessageId
|
||||
*/
|
||||
public getLastMessageId (): number
|
||||
}
|
||||
export { IClientOptions }
|
||||
19
WebUI/node_modules/mqtt/types/lib/connect/index.d.ts
generated
vendored
Normal file
19
WebUI/node_modules/mqtt/types/lib/connect/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { IClientOptions, MqttClient } from '../client'
|
||||
|
||||
/**
|
||||
* connect - connect to an MQTT broker.
|
||||
*
|
||||
* @param {Object} opts - see MqttClient#constructor
|
||||
*/
|
||||
declare function connect (opts: IClientOptions): MqttClient
|
||||
|
||||
/**
|
||||
* connect - connect to an MQTT broker.
|
||||
*
|
||||
* @param {String} brokerUrl - url of the broker
|
||||
* @param {Object} opts - see MqttClient#constructor
|
||||
*/
|
||||
declare function connect (brokerUrl: string, opts?: IClientOptions): MqttClient
|
||||
|
||||
export { connect }
|
||||
export { MqttClient }
|
||||
49
WebUI/node_modules/mqtt/types/lib/default-message-id-provider.d.ts
generated
vendored
Normal file
49
WebUI/node_modules/mqtt/types/lib/default-message-id-provider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { IMessageIdProvider } from './message-id-provider'
|
||||
|
||||
/**
|
||||
* DefaultMessageIdProvider
|
||||
* This is compatible behavior with the original MQTT.js internal messageId allocation.
|
||||
*/
|
||||
declare class DefaultMessageIdProvider implements IMessageIdProvider {
|
||||
/**
|
||||
* DefaultMessageIdProvider constructor.
|
||||
* Randomize initial messageId
|
||||
* @constructor
|
||||
*/
|
||||
constructor ()
|
||||
|
||||
/**
|
||||
* Return the current messageId and increment the current messageId.
|
||||
* @return {Number} - messageId
|
||||
*/
|
||||
public allocate (): Number | null
|
||||
|
||||
/**
|
||||
* Get the last allocated messageId.
|
||||
* @return {Number} - messageId.
|
||||
*/
|
||||
public getLastAllocated (): Number | null
|
||||
|
||||
/**
|
||||
* Register the messageId.
|
||||
* This function actually nothing and always return true.
|
||||
* @param {Number} num - The messageId to request use.
|
||||
* @return {Boolean} - If `num` was not occupied, then return true, otherwise return false.
|
||||
*/
|
||||
public register (num: Number): Boolean
|
||||
|
||||
/**
|
||||
* Deallocate the messageId.
|
||||
* This function actually nothing.
|
||||
* @param {Number} num - The messageId to deallocate.
|
||||
*/
|
||||
public deallocate (num: Number): void
|
||||
|
||||
/**
|
||||
* Clear all occupied messageIds.
|
||||
* This function actually nothing.
|
||||
*/
|
||||
public clear (): void
|
||||
}
|
||||
|
||||
export { DefaultMessageIdProvider }
|
||||
40
WebUI/node_modules/mqtt/types/lib/message-id-provider.d.ts
generated
vendored
Normal file
40
WebUI/node_modules/mqtt/types/lib/message-id-provider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* MessageIdProvider
|
||||
*/
|
||||
declare interface IMessageIdProvider {
|
||||
/**
|
||||
* Allocate the first vacant messageId. The messageId become occupied status.
|
||||
* @return {Number} - The first vacant messageId. If all messageIds are occupied, return null.
|
||||
*/
|
||||
allocate (): Number | null
|
||||
|
||||
/**
|
||||
* Get the last allocated messageId.
|
||||
* @return {Number} - messageId.
|
||||
*/
|
||||
getLastAllocated (): Number | null
|
||||
|
||||
/**
|
||||
* Register the messageId. The messageId become occupied status.
|
||||
* If the messageId has already been occupied, then return false.
|
||||
* @param {Number} num - The messageId to request use.
|
||||
* @return {Boolean} - If `num` was not occupied, then return true, otherwise return false.
|
||||
*/
|
||||
register (num: Number): Boolean
|
||||
|
||||
/**
|
||||
* Deallocate the messageId. The messageId become vacant status.
|
||||
* @param {Number} num - The messageId to deallocate. The messageId must be occupied status.
|
||||
* In other words, the messageId must be allocated by allocate() or
|
||||
* occupied by register().
|
||||
*/
|
||||
deallocate (num: Number): void
|
||||
|
||||
/**
|
||||
* Clear all occupied messageIds.
|
||||
* The all messageIds are set to vacant status.
|
||||
*/
|
||||
clear (): void
|
||||
}
|
||||
|
||||
export { IMessageIdProvider }
|
||||
6
WebUI/node_modules/mqtt/types/lib/store-options.d.ts
generated
vendored
Normal file
6
WebUI/node_modules/mqtt/types/lib/store-options.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface IStoreOptions {
|
||||
/**
|
||||
* true, clear _inflights at close
|
||||
*/
|
||||
clean?: boolean
|
||||
}
|
||||
46
WebUI/node_modules/mqtt/types/lib/store.d.ts
generated
vendored
Normal file
46
WebUI/node_modules/mqtt/types/lib/store.d.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
IStoreOptions
|
||||
} from './store-options'
|
||||
|
||||
/**
|
||||
* In-memory implementation of the message store
|
||||
* This can actually be saved into files.
|
||||
*
|
||||
*/
|
||||
declare class Store {
|
||||
/**
|
||||
* Store constructor
|
||||
*
|
||||
* @param {Object} [options] - store options
|
||||
*/
|
||||
constructor (options: IStoreOptions)
|
||||
|
||||
/**
|
||||
* Adds a packet to the store, a packet is
|
||||
* anything that has a messageId property.
|
||||
*
|
||||
*/
|
||||
public put (packet: any, cb?: Function): this
|
||||
|
||||
/**
|
||||
* Creates a stream with all the packets in the store
|
||||
*
|
||||
*/
|
||||
public createStream (): any
|
||||
|
||||
/**
|
||||
* deletes a packet from the store.
|
||||
*/
|
||||
public del (packet: any, cb: Function): this
|
||||
|
||||
/**
|
||||
* get a packet from the store.
|
||||
*/
|
||||
public get (packet: any, cb: Function): this
|
||||
|
||||
/**
|
||||
* Close the store
|
||||
*/
|
||||
public close (cb: Function): void
|
||||
}
|
||||
export { Store }
|
||||
48
WebUI/node_modules/mqtt/types/lib/unique-message-id-provider.d.ts
generated
vendored
Normal file
48
WebUI/node_modules/mqtt/types/lib/unique-message-id-provider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import { IMessageIdProvider } from './message-id-provider'
|
||||
|
||||
/**
|
||||
* UniqueMessageIdProvider
|
||||
*/
|
||||
declare class UniqueMessageIdProvider implements IMessageIdProvider {
|
||||
/**
|
||||
* UniqueMessageIdProvider constructor.
|
||||
* @constructor
|
||||
*/
|
||||
constructor ()
|
||||
|
||||
/**
|
||||
* Allocate the first vacant messageId. The messageId become occupied status.
|
||||
* @return {Number} - The first vacant messageId. If all messageIds are occupied, return null.
|
||||
*/
|
||||
public allocate (): Number | null
|
||||
|
||||
/**
|
||||
* Get the last allocated messageId.
|
||||
* @return {Number} - messageId.
|
||||
*/
|
||||
public getLastAllocated (): Number | null
|
||||
|
||||
/**
|
||||
* Register the messageId. The messageId become occupied status.
|
||||
* If the messageId has already been occupied, then return false.
|
||||
* @param {Number} num - The messageId to request use.
|
||||
* @return {Boolean} - If `num` was not occupied, then return true, otherwise return false.
|
||||
*/
|
||||
public register (num: Number): Boolean
|
||||
|
||||
/**
|
||||
* Deallocate the messageId. The messageId become vacant status.
|
||||
* @param {Number} num - The messageId to deallocate. The messageId must be occupied status.
|
||||
* In other words, the messageId must be allocated by allocate() or
|
||||
* occupied by register().
|
||||
*/
|
||||
public deallocate (num: Number): void
|
||||
|
||||
/**
|
||||
* Clear all occupied messageIds.
|
||||
* The all messageIds are set to vacant status.
|
||||
*/
|
||||
public clear (): void
|
||||
}
|
||||
|
||||
export { UniqueMessageIdProvider }
|
||||
Reference in New Issue
Block a user