UNPKG

botframework-streaming

Version:

Streaming library for the Microsoft Bot Framework

132 lines 7.09 kB
"use strict"; 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.NamedPipeServer = void 0; const namedPipeTransport_1 = require("./namedPipeTransport"); const payloadTransport_1 = require("../payloadTransport"); const protocolAdapter_1 = require("../protocolAdapter"); const payloads_1 = require("../payloads"); const createNodeServer_1 = require("../utilities/createNodeServer"); /** * Streaming transport server implementation that uses named pipes for inter-process communication. */ class NamedPipeServer { /** * Creates a new instance of the [NamedPipeServer](xref:botframework-streaming.NamedPipeServer) class. * * @param baseName The named pipe to connect to. * @param requestHandler Optional [RequestHandler](xref:botframework-streaming.RequestHandler) to process incoming messages received by this client. * @param autoReconnect Deprecated: Automatic reconnection is the default behavior. */ constructor(baseName, requestHandler, autoReconnect) { this.baseName = baseName; this._sender = new payloadTransport_1.PayloadSender(); this._receiver = new payloadTransport_1.PayloadReceiver(); if (!baseName) { throw new TypeError('NamedPipeServer: Missing baseName parameter'); } if (autoReconnect != null) { console.warn('NamedPipeServer: The autoReconnect parameter is deprecated'); } this._sender = new payloadTransport_1.PayloadSender(); this._receiver = new payloadTransport_1.PayloadReceiver(); this._protocolAdapter = new protocolAdapter_1.ProtocolAdapter(requestHandler, new payloads_1.RequestManager(), this._sender, this._receiver); } /** * Get connected status * * @returns true if currently connected. */ get isConnected() { return this._receiver.isConnected && this._sender.isConnected; } /** * Used to establish the connection used by this server and begin listening for incoming messages. * * @param onListen Optional callback that fires once when server is listening on both incoming and outgoing pipe * @returns A promised string that will not resolve as long as the server is running. */ start(onListen) { return __awaiter(this, void 0, void 0, function* () { const { PipePath, ServerIncomingPath, ServerOutgoingPath } = namedPipeTransport_1.NamedPipeTransport; // The first promise resolves as soon as the server is listening. The second resolves when the server // closes, or an error occurs. Wrapping with an array ensures the initial await only waits for the listening // promise. // // We want to ensure we are listening to the servers in series so that, if two processes start at the same // time, only one is able to listen on both the incoming and outgoing sockets. const [incoming] = yield new Promise((resolveListening, rejectListening) => { const server = (0, createNodeServer_1.createNodeServer)((socket) => { if (this._receiver.isConnected) { return; } this._receiver.connect(new namedPipeTransport_1.NamedPipeTransport(socket)); }).once('error', rejectListening); this._incomingServer = server; const isListening = new Promise((resolveClosed, rejectClosed) => { // Only register rejection once the server is actually listening server.once('listening', () => server.once('error', rejectClosed)); server.once('closed', resolveClosed); }); server.once('listening', () => resolveListening([isListening])); server.listen(PipePath + this.baseName + ServerIncomingPath); }); // Now that we absolutely have the incoming socket, bind the outgoing socket as well const [outgoing] = yield new Promise((resolveListening, rejectListening) => { const server = (0, createNodeServer_1.createNodeServer)((socket) => { if (this._sender.isConnected) { return; } // Note: manually disconnect sender if client closes socket. This ensures that // reconnections are allowed this._sender.connect(new namedPipeTransport_1.NamedPipeTransport(socket)); socket.once('close', () => this._sender.disconnect()); }).once('error', rejectListening); this._outgoingServer = server; const isListening = new Promise((resolveClosed, rejectClosed) => { // Only register rejection once the server is actually listening server.once('listening', () => server.once('error', rejectClosed)); server.once('closed', resolveClosed); }); server.once('listening', () => resolveListening([isListening])); server.listen(PipePath + this.baseName + ServerOutgoingPath); }); onListen === null || onListen === void 0 ? void 0 : onListen(); yield Promise.all([incoming, outgoing]); return 'connected'; }); } /** * Allows for manually disconnecting the server. */ disconnect() { var _a, _b; this._receiver.disconnect(); (_a = this._incomingServer) === null || _a === void 0 ? void 0 : _a.close(); this._incomingServer = null; this._sender.disconnect(); (_b = this._outgoingServer) === null || _b === void 0 ? void 0 : _b.close(); this._outgoingServer = null; } /** * Task used to send data over this client connection. * * @param request The [StreamingRequest](xref:botframework-streaming.StreamingRequest) to send. * @returns A promise for an instance of [IReceiveResponse](xref:botframework-streaming.IReceiveResponse) on completion of the send operation. */ send(request) { return __awaiter(this, void 0, void 0, function* () { return this._protocolAdapter.sendRequest(request); }); } } exports.NamedPipeServer = NamedPipeServer; //# sourceMappingURL=namedPipeServer.js.map