UNPKG

aws-crt

Version:

NodeJS bindings to the aws-c-* libraries

226 lines 8.71 kB
"use strict"; /* Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ 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 __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const mqtt_1 = require("mqtt"); const async_mqtt_1 = require("async-mqtt"); const WebsocketUtils = __importStar(require("./ws")); const trie = __importStar(require("./trie")); const event_1 = require("../common/event"); const browser_1 = require("../browser"); var mqtt_2 = require("../common/mqtt"); exports.QoS = mqtt_2.QoS; exports.MqttWill = mqtt_2.MqttWill; class MqttClient { new_connection(config) { return new MqttClientConnection(this, config); } } exports.MqttClient = MqttClient; class TopicTrie extends trie.Trie { constructor() { super('/'); } find_node(key, op) { const parts = this.split_key(key); let current = this.root; let parent = undefined; for (const part in parts) { let child = current.children.get(part); if (!child) { child = current.children.get('#'); if (child) { return child; } child = current.children.get('+'); } if (!child) { if (op == trie.TrieOp.Insert) { current.children.set(part, child = new trie.Node(part)); } else { return undefined; } } parent = current; current = child; } if (parent && op == trie.TrieOp.Delete) { parent.children.delete(current.key); } return current; } } function normalize_payload(payload) { let payload_data = payload.toString(); if (payload instanceof DataView) { payload_data = new TextDecoder('utf8').decode(payload); } else if (payload instanceof Object) { // Convert payload to JSON string payload_data = JSON.stringify(payload); } return payload_data; } class MqttClientConnection extends event_1.BufferedEventEmitter { constructor(client, config) { super(); this.client = client; this.config = config; this.subscriptions = new TopicTrie(); this.connection_count = 0; this.on_online = (session_present) => { if (++this.connection_count == 1) { this.emit('connect', session_present); } else { this.emit('resume', 0, session_present); } }; this.on_offline = () => { this.emit('interrupt', -1); }; this.on_disconnected = () => { this.emit('disconnect'); }; this.on_message = (topic, payload, packet) => { const callback = this.subscriptions.find(topic); if (callback) { callback(topic, payload); } this.emit('message', topic, payload); }; const create_websocket_stream = (client) => WebsocketUtils.create_websocket_stream(this.config); const transform_websocket_url = (url, options, client) => WebsocketUtils.create_websocket_url(this.config); this.connection = new async_mqtt_1.AsyncClient(new mqtt_1.MqttClient(create_websocket_stream, { keepalive: this.config.socket_options.keepalive ? this.config.socket_options.keep_alive_interval_sec : 0, clientId: this.config.client_id, connectTimeout: this.config.socket_options.connect_timeout_ms, clean: this.config.clean_session, username: this.config.username, password: this.config.password, reconnectPeriod: 0, will: this.config.will ? { topic: this.config.will.topic, payload: normalize_payload(this.config.will.payload), qos: this.config.will.qos, retain: this.config.will.retain, } : undefined, transformWsUrl: (config.websocket || {}).protocol != 'wss-custom-auth' ? transform_websocket_url : undefined })); } // Override to allow uncorking on connect on(event, listener) { super.on(event, listener); if (event == 'connect') { process.nextTick(() => { this.uncork(); }); } return this; } _reject(reject) { return (reason) => { reject(reason); this.emit('error', new browser_1.CrtError(reason)); }; } connect() { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { reject = this._reject(reject); try { this.connection.on('connect', (connack) => { resolve(connack.sessionPresent); this.on_online(connack.sessionPresent); }); this.connection.on('error', (error) => { reject(`Failed to connect: error=${error}`); }); this.connection.on('message', this.on_message); this.connection.on('offline', this.on_offline); this.connection.on('end', this.on_disconnected); } catch (e) { reject(e); } }); }); } reconnect() { return __awaiter(this, void 0, void 0, function* () { return this.connect(); }); } publish(topic, payload, qos, retain = false) { return __awaiter(this, void 0, void 0, function* () { let payload_data = normalize_payload(payload); return this.connection.publish(topic, payload_data, { qos: qos, retain: retain }) .catch((reason) => { this.emit('error', new browser_1.CrtError(reason)); }) .then((value) => { return { packet_id: value.messageId }; }); }); } subscribe(topic, qos, on_message) { return __awaiter(this, void 0, void 0, function* () { this.subscriptions.insert(topic, on_message); return this.connection.subscribe(topic, { qos: qos }) .catch((reason) => { this.emit('error', new browser_1.CrtError(reason)); }) .then((value) => { const sub = value[0]; return { topic: sub.topic, qos: sub.qos }; }); }); } unsubscribe(topic) { return __awaiter(this, void 0, void 0, function* () { this.subscriptions.remove(topic); return this.connection.unsubscribe(topic) .catch((reason) => { this.emit('error', new browser_1.CrtError(reason)); }) .then((value) => { return { packet_id: value.messageId }; }); }); } disconnect() { return __awaiter(this, void 0, void 0, function* () { return this.connection.end(); }); } } exports.MqttClientConnection = MqttClientConnection; //# sourceMappingURL=mqtt.js.map