UNPKG

botframework-streaming

Version:

Streaming library for the Microsoft Bot Framework

106 lines (90 loc) 3.55 kB
/** * @module botframework-streaming */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ import { HeaderSerializer } from '../payloads/headerSerializer'; import { IHeader, ISendPacket, ITransportSender } from '../interfaces'; import { PayloadConstants } from '../payloads/payloadConstants'; import { SubscribableStream } from '../subscribableStream'; import { TransportDisconnectedEvent } from './transportDisconnectedEvent'; import { TransportDisconnectedEventHandler } from './transportDisconnectedEventHandler'; /** * Streaming payload sender. */ export class PayloadSender { disconnected?: TransportDisconnectedEventHandler; private _sender: ITransportSender; /** * Get current connected state * * @returns true if connected to a transport sender. */ get isConnected(): boolean { return this._sender != null; } /** * Connects to the given transport sender. * * @param sender The transport sender to connect this payload sender to. */ connect(sender: ITransportSender): void { this._sender = sender; } /** * Sends a payload out over the connected transport sender. * * @param header The header to attach to the outgoing payload. * @param payload The stream of buffered data to send. * @param sentCallback The function to execute when the send has completed. */ sendPayload(header: IHeader, payload?: SubscribableStream, sentCallback?: () => Promise<void>): void { const packet: ISendPacket = { header, payload, sentCallback }; this.writePacket(packet); } /** * Disconnects this payload sender. * * @param event The disconnected event arguments to include in the disconnected event broadcast. */ disconnect(event = TransportDisconnectedEvent.Empty): void { if (!this.isConnected) { return; } try { this._sender.close(); this.disconnected?.(this, event); } catch (err) { this.disconnected?.(this, new TransportDisconnectedEvent(err.message)); } finally { this._sender = null; } } private writePacket(packet: ISendPacket): void { try { if (packet.header.payloadLength > 0 && packet.payload) { let leftOver = packet.header.payloadLength; while (leftOver > 0) { const count = leftOver <= PayloadConstants.MaxPayloadLength ? leftOver : PayloadConstants.MaxPayloadLength; const chunk = packet.payload.read(count); const header = packet.header; header.payloadLength = count; header.end = leftOver <= PayloadConstants.MaxPayloadLength; const sendHeaderBuffer: Buffer = Buffer.alloc(PayloadConstants.MaxHeaderLength); HeaderSerializer.serialize(header, sendHeaderBuffer); this._sender.send(sendHeaderBuffer); this._sender.send(chunk); leftOver -= chunk.length; } if (packet.sentCallback) { packet.sentCallback(); } } } catch (err) { this.disconnect(new TransportDisconnectedEvent(err.message)); } } }