File Explorer

/proc/self/root/var/runtime/node_modules/@aws-sdk/node_modules/aws-crt/dist.browser/browser

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

mqtt.js29.8 KB · 640 lines
"use strict";/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */var __extends = (this && this.__extends) || (function () {    var extendStatics = function (d, b) {        extendStatics = Object.setPrototypeOf ||            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };        return extendStatics(d, b);    };    return function (d, b) {        if (typeof b !== "function" && b !== null)            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");        extendStatics(d, b);        function __() { this.constructor = d; }        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());    };})();var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {    if (k2 === undefined) k2 = k;    var desc = Object.getOwnPropertyDescriptor(m, k);    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {      desc = { enumerable: true, get: function() { return m[k]; } };    }    Object.defineProperty(o, k2, desc);}) : (function(o, m, k, k2) {    if (k2 === undefined) k2 = k;    o[k2] = m[k];}));var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {    Object.defineProperty(o, "default", { enumerable: true, value: v });}) : function(o, v) {    o["default"] = v;});var __importStar = (this && this.__importStar) || function (mod) {    if (mod && mod.__esModule) return mod;    var result = {};    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);    __setModuleDefault(result, mod);    return result;};var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }    return new (P || (P = Promise))(function (resolve, reject) {        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }        step((generator = generator.apply(thisArg, _arguments || [])).next());    });};var __generator = (this && this.__generator) || function (thisArg, body) {    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;    function verb(n) { return function (v) { return step([n, v]); }; }    function step(op) {        if (f) throw new TypeError("Generator is already executing.");        while (g && (g = 0, op[0] && (_ = 0)), _) try {            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;            if (y = 0, t) op = [op[0] & 2, t.value];            switch (op[0]) {                case 0: case 1: t = op; break;                case 4: _.label++; return { value: op[1], done: false };                case 5: _.label++; y = op[1]; op = [0]; continue;                case 7: op = _.ops.pop(); _.trys.pop(); continue;                default:                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }                    if (t[2]) _.ops.pop();                    _.trys.pop(); continue;            }            op = body.call(thisArg, _);        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };    }};var __values = (this && this.__values) || function(o) {    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;    if (m) return m.call(o);    if (o && typeof o.length === "number") return {        next: function () {            if (o && i >= o.length) o = void 0;            return { value: o && o[i++], done: !o };        }    };    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");};Object.defineProperty(exports, "__esModule", { value: true });exports.MqttClientConnection = exports.MqttClient = exports.MqttWill = exports.QoS = void 0;/** * * A module containing support for mqtt connection establishment and operations. * * @packageDocumentation * @module mqtt * @mergeTarget */var mqtt = __importStar(require("mqtt"));var WebsocketUtils = __importStar(require("./ws"));var auth = __importStar(require("./auth"));var trie_1 = require("./trie");var event_1 = require("../common/event");var browser_1 = require("../browser");var mqtt_1 = require("../common/mqtt");var mqtt_shared_1 = require("../common/mqtt_shared");var mqtt_2 = require("../common/mqtt");Object.defineProperty(exports, "QoS", { enumerable: true, get: function () { return mqtt_2.QoS; } });Object.defineProperty(exports, "MqttWill", { enumerable: true, get: function () { return mqtt_2.MqttWill; } });/** * MQTT client * * @category MQTT */var MqttClient = /** @class */ (function () {    function MqttClient(bootstrap) {    }    /**     * Creates a new {@link MqttClientConnection}     * @param config Configuration for the connection     * @returns A new connection     */    MqttClient.prototype.new_connection = function (config) {        return new MqttClientConnection(this, config);    };    return MqttClient;}());exports.MqttClient = MqttClient;/** * @internal */var MqttBrowserClientState;(function (MqttBrowserClientState) {    MqttBrowserClientState[MqttBrowserClientState["Connected"] = 0] = "Connected";    MqttBrowserClientState[MqttBrowserClientState["Stopped"] = 1] = "Stopped";})(MqttBrowserClientState || (MqttBrowserClientState = {}));;/** @internal */var TopicTrie = /** @class */ (function (_super) {    __extends(TopicTrie, _super);    function TopicTrie() {        return _super.call(this, '/') || this;    }    TopicTrie.prototype.find_node = function (key, op) {        var e_1, _a;        var parts = this.split_key(key);        var current = this.root;        var parent = undefined;        try {            for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) {                var part = parts_1_1.value;                var child = current.children.get(part);                if (!child) {                    child = current.children.get('#');                    if (child) {                        return child;                    }                    child = current.children.get('+');                }                if (!child) {                    if (op == trie_1.TrieOp.Insert) {                        current.children.set(part, child = new trie_1.Node(part));                    }                    else {                        return undefined;                    }                }                parent = current;                current = child;            }        }        catch (e_1_1) { e_1 = { error: e_1_1 }; }        finally {            try {                if (parts_1_1 && !parts_1_1.done && (_a = parts_1.return)) _a.call(parts_1);            }            finally { if (e_1) throw e_1.error; }        }        if (parent && op == trie_1.TrieOp.Delete) {            parent.children.delete(current.key);        }        return current;    };    return TopicTrie;}(trie_1.Trie));/** * MQTT client connection * * @category MQTT */var MqttClientConnection = /** @class */ (function (_super) {    __extends(MqttClientConnection, _super);    /**     * @param client The client that owns this connection     * @param config The configuration for this connection     */    function MqttClientConnection(client, config) {        var _this = _super.call(this) || this;        _this.client = client;        _this.config = config;        _this.subscriptions = new TopicTrie();        _this.connection_count = 0;        // track number of times in a row that reconnect has been attempted        // use exponential backoff between subsequent failed attempts        _this.reconnect_count = 0;        _this.reconnect_min_sec = mqtt_1.DEFAULT_RECONNECT_MIN_SEC;        _this.reconnect_max_sec = mqtt_1.DEFAULT_RECONNECT_MAX_SEC;        _this.currentState = MqttBrowserClientState.Stopped;        _this.desiredState = MqttBrowserClientState.Stopped;        _this.on_connect = function (connack) {            _this.on_online(connack.sessionPresent);        };        _this.on_online = function (session_present) {            _this.currentState = MqttBrowserClientState.Connected;            if (++_this.connection_count == 1) {                _this.emit('connect', session_present);            }            else {                /** Reset reconnect times after reconnect succeed. */                _this.reset_reconnect_times();                _this.emit('resume', 0, session_present);            }            // Call connection success every time we connect, whether it is a first connect or a reconnect            var successCallbackData = { session_present: session_present };            _this.emit('connection_success', successCallbackData);        };        _this.on_close = function () {            var _a;            var lastError = _this.lastError;            /*             * Only emit an interruption event if we were connected, otherwise we just failed to reconnect after             * a disconnection.             */            if (_this.currentState == MqttBrowserClientState.Connected) {                _this.currentState = MqttBrowserClientState.Stopped;                _this.emit('interrupt', -1);                /* Did we intend to disconnect? If so, then emit the event */                if (_this.desiredState == MqttBrowserClientState.Stopped) {                    _this.emit("closed");                }            }            /* Only try and reconnect if our desired state is connected, or in other words, no one has called disconnect() */            if (_this.desiredState == MqttBrowserClientState.Connected) {                var crtError = new browser_1.CrtError((_a = lastError === null || lastError === void 0 ? void 0 : lastError.toString()) !== null && _a !== void 0 ? _a : "connectionFailure");                var failureCallbackData = { error: crtError };                _this.emit('connection_failure', failureCallbackData);                var waitTime = _this.get_reconnect_time_sec();                _this.reconnectTask = setTimeout(function () {                    /** Emit reconnect after backoff time */                    _this.reconnect_count++;                    _this.connection.reconnect();                }, waitTime * 1000);            }            _this.lastError = undefined;        };        _this.on_disconnected = function () {            _this.emit('disconnect');            /**             * This shouldn't ever occur, but in THEORY it could be possible to have on_disconnected called with the intent             * to disconnect without on_close called first. This would properly emit 'closed' should that unlikely event occur.             */            if (_this.currentState == MqttBrowserClientState.Connected && _this.desiredState == MqttBrowserClientState.Stopped) {                var closedCallbackData = {};                _this.emit("closed", closedCallbackData);            }        };        _this.on_error = function (error) {            _this.lastError = error;            _this.emit('error', new browser_1.CrtError(error));        };        _this.on_message = function (topic, payload, packet) {            // pass payload as ArrayBuffer            var array_buffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);            var callback = _this.subscriptions.find(topic);            if (callback) {                callback(topic, array_buffer, packet.dup, packet.qos, packet.retain);            }            _this.emit('message', topic, array_buffer, packet.dup, packet.qos, packet.retain);        };        var create_websocket_stream = function (client) { return WebsocketUtils.create_websocket_stream(_this.config); };        var transform_websocket_url = function (url, options, client) { return WebsocketUtils.create_websocket_url(_this.config); };        if (config == null || config == undefined) {            throw new browser_1.CrtError("MqttClientConnection constructor: config not defined");        }        var will = _this.config.will ? {            topic: _this.config.will.topic,            payload: (0, mqtt_shared_1.normalize_payload_to_buffer)(_this.config.will.payload),            qos: _this.config.will.qos,            retain: _this.config.will.retain,        } : undefined;        if (config.reconnect_min_sec !== undefined) {            _this.reconnect_min_sec = config.reconnect_min_sec;            // clamp max, in case they only passed in min            _this.reconnect_max_sec = Math.max(_this.reconnect_min_sec, _this.reconnect_max_sec);        }        if (config.reconnect_max_sec !== undefined) {            _this.reconnect_max_sec = config.reconnect_max_sec;            // clamp min, in case they only passed in max (or passed in min > max)            _this.reconnect_min_sec = Math.min(_this.reconnect_min_sec, _this.reconnect_max_sec);        }        _this.reset_reconnect_times();        // If the credentials are set but no the credentials_provider        if (_this.config.credentials_provider == undefined &&            _this.config.credentials != undefined) {            var provider = new auth.StaticCredentialProvider({ aws_region: _this.config.credentials.aws_region,                aws_access_id: _this.config.credentials.aws_access_id,                aws_secret_key: _this.config.credentials.aws_secret_key,                aws_sts_token: _this.config.credentials.aws_sts_token });            _this.config.credentials_provider = provider;        }        var websocketXform = (_this.config.websocket || {}).protocol != 'wss-custom-auth' ? transform_websocket_url : undefined;        _this.connection = new mqtt.MqttClient(create_websocket_stream, {            // service default is 1200 seconds            keepalive: _this.config.keep_alive ? _this.config.keep_alive : 1200,            clientId: _this.config.client_id,            connectTimeout: _this.config.ping_timeout ? _this.config.ping_timeout : 30 * 1000,            clean: _this.config.clean_session,            username: _this.config.username,            password: _this.config.password,            reconnectPeriod: _this.reconnect_max_sec * 1000,            will: will,            transformWsUrl: websocketXform,        });        _this.connection.on('connect', _this.on_connect);        _this.connection.on('error', _this.on_error);        _this.connection.on('message', _this.on_message);        _this.connection.on('close', _this.on_close);        _this.connection.on('end', _this.on_disconnected);        return _this;    }    MqttClientConnection.prototype.on = function (event, listener) {        return _super.prototype.on.call(this, event, listener);    };    /**     * Open the actual connection to the server (async).     * @returns A Promise which completes whether the connection succeeds or fails.     *          If connection fails, the Promise will reject with an exception.     *          If connection succeeds, the Promise will return a boolean that is     *          true for resuming an existing session, or false if the session is new     */    MqttClientConnection.prototype.connect = function () {        return __awaiter(this, void 0, void 0, function () {            var _this = this;            return __generator(this, function (_a) {                this.desiredState = MqttBrowserClientState.Connected;                setTimeout(function () { _this.uncork(); }, 0);                return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {                        var provider, on_connect_error;                        var _this = this;                        return __generator(this, function (_a) {                            switch (_a.label) {                                case 0:                                    provider = this.config.credentials_provider;                                    if (!provider) return [3 /*break*/, 2];                                    return [4 /*yield*/, provider.refreshCredentials()];                                case 1:                                    _a.sent();                                    _a.label = 2;                                case 2:                                    on_connect_error = function (error) {                                        var crtError = new browser_1.CrtError(error);                                        var failureCallbackData = { error: crtError };                                        _this.emit('connection_failure', failureCallbackData);                                        reject(crtError);                                    };                                    this.connection.once('error', on_connect_error);                                    this.connection.once('connect', function (connack) {                                        _this.connection.removeListener('error', on_connect_error);                                        resolve(connack.sessionPresent);                                    });                                    return [2 /*return*/];                            }                        });                    }); })];            });        });    };    /**     * The connection will automatically reconnect. To cease reconnection attempts, call {@link disconnect}.     * To resume the connection, call {@link connect}.     * @deprecated     */    MqttClientConnection.prototype.reconnect = function () {        return __awaiter(this, void 0, void 0, function () {            return __generator(this, function (_a) {                return [2 /*return*/, this.connect()];            });        });    };    /**     * Publish message (async).     * If the device is offline, the PUBLISH packet will be sent once the connection resumes.     *     * @param topic Topic name     * @param payload Contents of message     * @param qos Quality of Service for delivering this message     * @param retain If true, the server will store the message and its QoS so that it can be     *               delivered to future subscribers whose subscriptions match the topic name     * @returns Promise which returns a {@link MqttRequest} which will contain the packet id of     *          the PUBLISH packet.     *     * * For QoS 0, completes as soon as the packet is sent.     * * For QoS 1, completes when PUBACK is received.     * * For QoS 2, completes when PUBCOMP is received.     */    MqttClientConnection.prototype.publish = function (topic, payload, qos, retain) {        if (retain === void 0) { retain = false; }        return __awaiter(this, void 0, void 0, function () {            var payload_data;            var _this = this;            return __generator(this, function (_a) {                // Skip payload since it can be several different types                if (typeof (topic) !== 'string') {                    return [2 /*return*/, Promise.reject("topic is not a string")];                }                if (typeof (qos) !== 'number') {                    return [2 /*return*/, Promise.reject("qos is not a number")];                }                if (typeof (retain) !== 'boolean') {                    return [2 /*return*/, Promise.reject('retain is not a boolean')];                }                payload_data = (0, mqtt_shared_1.normalize_payload)(payload);                return [2 /*return*/, new Promise(function (resolve, reject) {                        _this.connection.publish(topic, payload_data, { qos: qos, retain: retain }, function (error, packet) {                            if (error) {                                reject(new browser_1.CrtError(error));                                return _this.on_error(error);                            }                            var id = undefined;                            if (qos != mqtt_1.QoS.AtMostOnce) {                                id = packet.messageId;                            }                            resolve({ packet_id: id });                        });                    })];            });        });    };    /**     * Subscribe to a topic filter (async).     * The client sends a SUBSCRIBE packet and the server responds with a SUBACK.     *     * subscribe() may be called while the device is offline, though the async     * operation cannot complete successfully until the connection resumes.     *     * Once subscribed, `callback` is invoked each time a message matching     * the `topic` is received. It is possible for such messages to arrive before     * the SUBACK is received.     *     * @param topic Subscribe to this topic filter, which may include wildcards     * @param qos Maximum requested QoS that server may use when sending messages to the client.     *            The server may grant a lower QoS in the SUBACK     * @param on_message Optional callback invoked when message received.     * @returns Promise which returns a {@link MqttSubscribeRequest} which will contain the     *          result of the SUBSCRIBE. The Promise resolves when a SUBACK is returned     *          from the server or is rejected when an exception occurs.     */    MqttClientConnection.prototype.subscribe = function (topic, qos, on_message) {        return __awaiter(this, void 0, void 0, function () {            var _this = this;            return __generator(this, function (_a) {                if (typeof (topic) !== 'string') {                    return [2 /*return*/, Promise.reject("topic is not a string")];                }                if (typeof (qos) !== 'number') {                    return [2 /*return*/, Promise.reject("qos is not a number")];                }                this.subscriptions.insert(topic, on_message);                return [2 /*return*/, new Promise(function (resolve, reject) {                        _this.connection.subscribe(topic, { qos: qos }, function (error, packet) {                            if (error) {                                reject(new browser_1.CrtError(error));                                return _this.on_error(error);                            }                            var sub = packet[0];                            /*                             * 128 is not modeled in QoS, either on our side nor mqtt-js's side.                             * We have always passed this 128 to the user and it is not reasonable to extend                             * our output type with 128 since it's also our input type and we don't want anyone                             * to pass 128 to us.                             *                             * The 5 client solves this by making the output type a completely separate enum.                             *                             * By doing this cast, we make the type checker ignore this edge case.                             */                            resolve({ topic: sub.topic, qos: sub.qos });                        });                    })];            });        });    };    /**     * Unsubscribe from a topic filter (async).     * The client sends an UNSUBSCRIBE packet, and the server responds with an UNSUBACK.     * @param topic The topic filter to unsubscribe from. May contain wildcards.     * @returns Promise which returns a {@link MqttRequest} which will contain the packet id     *          of the UNSUBSCRIBE packet being acknowledged. Promise is resolved when an     *          UNSUBACK is received from the server or is rejected when an exception occurs.     */    MqttClientConnection.prototype.unsubscribe = function (topic) {        return __awaiter(this, void 0, void 0, function () {            var _this = this;            return __generator(this, function (_a) {                if (typeof (topic) !== 'string') {                    return [2 /*return*/, Promise.reject("topic is not a string")];                }                this.subscriptions.remove(topic);                return [2 /*return*/, new Promise(function (resolve, reject) {                        _this.connection.unsubscribe(topic, undefined, function (error, packet) {                            if (error) {                                reject(new browser_1.CrtError(error));                                return _this.on_error(error);                            }                            resolve({                                packet_id: packet                                    ? packet.messageId                                    : undefined,                            });                        });                    })];            });        });    };    /**     * Close the connection (async).     * @returns Promise which completes when the connection is closed.     */    MqttClientConnection.prototype.disconnect = function () {        return __awaiter(this, void 0, void 0, function () {            var _this = this;            return __generator(this, function (_a) {                this.desiredState = MqttBrowserClientState.Stopped;                /* If the user wants to disconnect, stop the recurrent connection task */                if (this.reconnectTask) {                    clearTimeout(this.reconnectTask);                    this.reconnectTask = undefined;                }                return [2 /*return*/, new Promise(function (resolve) {                        /*                         * The original implementation did not force the disconnect so in our update to fix the promise resolution,                         * we need to keep that contract.                         */                        _this.connection.end(false, {}, resolve);                    })];            });        });    };    /**     * Queries whether the client is currently connected     *     * @returns whether the client is currently connected     */    MqttClientConnection.prototype.is_connected = function () {        return this.currentState == MqttBrowserClientState.Connected;    };    MqttClientConnection.prototype.reset_reconnect_times = function () {        this.reconnect_count = 0;    };    /**     * Returns seconds until next reconnect attempt.     */    MqttClientConnection.prototype.get_reconnect_time_sec = function () {        if (this.reconnect_min_sec == 0 && this.reconnect_max_sec == 0) {            return 0;        }        // Uses "FullJitter" backoff algorithm, described here:        // https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/        // We slightly vary the algorithm described on the page,        // which takes (base,cap) and may result in 0.        // But we take (min,max) as parameters, and don't don't allow results less than min.        var cap = this.reconnect_max_sec - this.reconnect_min_sec;        var base = Math.max(this.reconnect_min_sec, 1);        /** Use Math.pow() since IE does not support ** operator */        var sleep = Math.random() * Math.min(cap, base * Math.pow(2, this.reconnect_count));        return this.reconnect_min_sec + sleep;    };    /**     * Emitted when the connection successfully establishes itself for the first time     *     * @event     */    MqttClientConnection.CONNECT = 'connect';    /**     * Emitted when connection has disconnected sucessfully.     *     * @event     */    MqttClientConnection.DISCONNECT = 'disconnect';    /**     * Emitted when an error occurs.  The error will contain the error     * code and message.     *     * @event     */    MqttClientConnection.ERROR = 'error';    /**     * Emitted when the connection is dropped unexpectedly. The error will contain the error     * code and message.  The underlying mqtt implementation will attempt to reconnect.     *     * @event     */    MqttClientConnection.INTERRUPT = 'interrupt';    /**     * Emitted when the connection reconnects (after an interrupt). Only triggers on connections after the initial one.     *     * @event     */    MqttClientConnection.RESUME = 'resume';    /**     * Emitted when any MQTT publish message arrives.     *     * @event     */    MqttClientConnection.MESSAGE = 'message';    /**     * Emitted on every successful connect and reconnect.     * Will contain a boolean indicating whether the connection resumed a session.     *     * @event     */    MqttClientConnection.CONNECTION_SUCCESS = 'connection_success';    /**     * Emitted on an unsuccessful connect and reconnect.     * Will contain an error code indicating the reason for the unsuccessful connection.     *     * @event     */    MqttClientConnection.CONNECTION_FAILURE = 'connection_failure';    /**     * Emitted when the MQTT connection was disconnected and shutdown successfully.     *     * @event     */    MqttClientConnection.CLOSED = 'closed';    return MqttClientConnection;}(event_1.BufferedEventEmitter));exports.MqttClientConnection = MqttClientConnection;//# sourceMappingURL=mqtt.js.map