UNPKG

botframework-streaming

Version:

Streaming library for the Microsoft Bot Framework

158 lines 5.88 kB
"use strict"; /** * @module botframework-streaming */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebSocketTransport = void 0; /** * Web socket based transport. */ class WebSocketTransport { /** * Creates a new instance of the [WebSocketTransport](xref:botframework-streaming.WebSocketTransport) class. * * @param ws The ISocket to build this transport on top of. */ constructor(ws) { this.ws = ws; this._queue = []; this._activeOffset = 0; this._activeReceiveCount = 0; this.ws.setOnMessageHandler((data) => { this.onReceive(data); }); this.ws.setOnErrorHandler((err) => { this.onError(err); }); this.ws.setOnCloseHandler(() => { this.onClose(); }); } /** * Sends the given buffer out over the socket's connection. * * @param buffer The buffered data to send out over the connection. * @returns A number indicating the length of the sent data if the data was successfully sent, otherwise 0. */ send(buffer) { var _a; if ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.isConnected) { this.ws.write(buffer); return buffer.length; } return 0; } /** * Returns true if the transport is connected to a socket. * * @returns `true` if the the transport is connected and ready to send data, `false` otherwise. */ get isConnected() { var _a; return !!((_a = this.ws) === null || _a === void 0 ? void 0 : _a.isConnected); } /** * Close the socket this transport is connected to. */ close() { var _a; if ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.isConnected) { this.ws.close(); } } /** * Attempt to receive incoming data from the connected socket. * * @param count The number of bytes to attempt to receive. * @returns A buffer populated with the received data. */ receive(count) { return __awaiter(this, void 0, void 0, function* () { if (this._activeReceiveResolve) { throw new Error('Cannot call receive more than once before it has returned.'); } this._activeReceiveCount = count; const promise = new Promise((resolve, reject) => { this._activeReceiveResolve = resolve; this._activeReceiveReject = reject; }); this.trySignalData(); return promise; }); } /** * Sets the transport to attempt to receive incoming data that has not yet arrived. * * @param data A buffer to store incoming data in. */ onReceive(data) { if (this._queue && data && data.byteLength > 0) { this._queue.push(Buffer.from(data)); this.trySignalData(); } } onClose() { if (this._activeReceiveReject) { this._activeReceiveReject(new Error('Socket was closed.')); } this._active = null; this._activeOffset = 0; this._activeReceiveResolve = null; this._activeReceiveReject = null; this._activeReceiveCount = 0; this.ws = null; } onError(err) { if (this._activeReceiveReject) { this._activeReceiveReject(err); } this.onClose(); } trySignalData() { if (this._activeReceiveResolve) { if (!this._active && this._queue.length > 0) { this._active = this._queue.shift(); this._activeOffset = 0; } if (this._active) { if (this._activeOffset === 0 && this._active.length === this._activeReceiveCount) { // can send the entire _active buffer const buffer = this._active; this._active = null; this._activeReceiveResolve(buffer); } else { // create a Buffer.from and copy some of the contents into it const available = Math.min(this._activeReceiveCount, this._active.length - this._activeOffset); const buffer = Buffer.alloc(available); this._active.copy(buffer, 0, this._activeOffset, this._activeOffset + available); this._activeOffset += available; // if we used all of active, set it to undefined if (this._activeOffset >= this._active.length) { this._active = null; this._activeOffset = 0; } this._activeReceiveResolve(buffer); } this._activeReceiveCount = 0; this._activeReceiveReject = null; this._activeReceiveResolve = null; } } } } exports.WebSocketTransport = WebSocketTransport; //# sourceMappingURL=webSocketTransport.js.map