aws-crt
Version:
NodeJS bindings to the aws-c-* libraries
255 lines • 10.9 kB
JavaScript
"use strict";
/*
* Copyright 2010-2019 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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
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 binding_1 = __importDefault(require("./binding"));
const native_resource_1 = require("./native_resource");
const event_1 = require("../common/event");
const error_1 = require("./error");
const io = __importStar(require("./io"));
const util_1 = require("util");
var http_1 = require("./http");
exports.HttpProxyOptions = http_1.HttpProxyOptions;
const mqtt_1 = require("../common/mqtt");
var mqtt_2 = require("../common/mqtt");
exports.QoS = mqtt_2.QoS;
exports.MqttWill = mqtt_2.MqttWill;
class MqttClient extends native_resource_1.NativeResource {
constructor(bootstrap) {
super(binding_1.default.mqtt_client_new(bootstrap.native_handle()));
this.bootstrap = bootstrap;
}
new_connection(config) {
return new MqttClientConnection(this, config);
}
}
exports.MqttClient = MqttClient;
const normalize_encoder = new util_1.TextEncoder();
function normalize_payload(payload) {
let payload_data;
if (payload instanceof DataView) {
// If payload is already dataview, just use it
payload_data = payload;
}
else {
if (typeof payload === 'object') {
// Convert payload to JSON string, next if block will turn it into a DataView.
payload = JSON.stringify(payload);
}
if (typeof payload === 'string') {
// Encode the string as UTF-8
payload_data = new DataView(normalize_encoder.encode(payload).buffer);
}
else {
throw new TypeError("payload parameter must be a string, object, or DataView.");
}
}
return payload_data;
}
class MqttClientConnection extends native_resource_1.NativeResourceMixin(event_1.BufferedEventEmitter) {
constructor(client, config) {
super();
this.client = client;
this.config = config;
this._super(binding_1.default.mqtt_client_connection_new(client.native_handle(), (error_code) => { this._on_connection_interrupted(error_code); }, (return_code, session_present) => { this._on_connection_resumed(return_code, session_present); }));
this.tls_ctx = config.tls_ctx;
}
close() {
binding_1.default.mqtt_client_connection_close(this.native_handle());
}
// Override to allow uncorking on ready
on(event, listener) {
super.on(event, listener);
if (event == 'connect') {
process.nextTick(() => {
this.uncork();
});
}
return this;
}
connect() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
const on_connect = (error_code, return_code, session_present) => {
if (error_code == 0 && return_code == 0) {
resolve(session_present);
this.emit('connect', session_present);
}
else if (error_code != 0) {
reject("Failed to connect: " + io.error_code_to_string(error_code));
}
else {
reject("Server rejected connection.");
}
};
// If there is a will, ensure that its payload is normalized to a DataView
const will = this.config.will ?
new mqtt_1.MqttWill(this.config.will.topic, this.config.will.qos, normalize_payload(this.config.will.payload), this.config.will.retain)
: undefined;
try {
binding_1.default.mqtt_client_connection_on_message(this.native_handle(), this._on_any_publish.bind(this));
binding_1.default.mqtt_client_connection_connect(this.native_handle(), this.config.client_id, this.config.host_name, this.config.port, this.config.tls_ctx ? this.config.tls_ctx.native_handle() : null, this.config.socket_options.native_handle(), this.config.keep_alive, this.config.timeout, will, this.config.username, this.config.password, this.config.use_websocket, this.config.proxy_options ? this.config.proxy_options.create_native_handle() : undefined, this.config.clean_session, on_connect, this.config.websocket_handshake_transform);
}
catch (e) {
reject(e);
}
});
});
}
reconnect() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
function on_connect(error_code, return_code, session_present) {
if (error_code == 0 && return_code == 0) {
resolve(session_present);
}
else if (error_code != 0) {
reject("Failed to connect: " + io.error_code_to_string(error_code));
}
else {
reject("Server rejected connection.");
}
}
try {
binding_1.default.mqtt_client_connection_reconnect(this.native_handle(), on_connect);
}
catch (e) {
reject(e);
}
});
});
}
publish(topic, payload, qos, retain = false) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
let payload_data = normalize_payload(payload);
function on_publish(packet_id, error_code) {
if (error_code == 0) {
resolve({ packet_id });
}
else {
reject("Failed to publish: " + io.error_code_to_string(error_code));
}
}
try {
binding_1.default.mqtt_client_connection_publish(this.native_handle(), topic, payload_data, qos, retain, on_publish);
}
catch (e) {
reject(e);
}
});
});
}
subscribe(topic, qos, on_message) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
function on_suback(packet_id, topic, qos, error_code) {
if (error_code == 0) {
resolve({ packet_id, topic, qos, error_code });
}
else {
reject("Failed to subscribe: " + io.error_code_to_string(error_code));
}
}
try {
binding_1.default.mqtt_client_connection_subscribe(this.native_handle(), topic, qos, on_message, on_suback);
}
catch (e) {
reject(e);
}
});
});
}
unsubscribe(topic) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
function on_unsuback(packet_id, error_code) {
if (error_code == 0) {
resolve({ packet_id });
}
else {
reject("Failed to unsubscribe: " + io.error_code_to_string(error_code));
}
}
try {
binding_1.default.mqtt_client_connection_unsubscribe(this.native_handle(), topic, on_unsuback);
}
catch (e) {
reject(e);
}
});
});
}
disconnect() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
reject = this._reject(reject);
const on_disconnect = () => {
resolve();
this.emit('disconnect');
this.close();
};
try {
binding_1.default.mqtt_client_connection_disconnect(this.native_handle(), on_disconnect);
}
catch (e) {
reject(e);
}
});
});
}
// Wrap a promise rejection with a function that will also emit the error as an event
_reject(reject) {
return (reason) => {
reject(reason);
this.emit('error', new error_1.CrtError(reason));
};
}
_on_connection_interrupted(error_code) {
this.emit('interrupt', new error_1.CrtError(error_code));
}
_on_connection_resumed(return_code, session_present) {
this.emit('resume', return_code, session_present);
}
_on_any_publish(topic, payload) {
this.emit('message', topic, payload);
}
}
exports.MqttClientConnection = MqttClientConnection;
//# sourceMappingURL=mqtt.js.map