UNPKG

nerdbank-streams

Version:
221 lines (220 loc) 11.6 kB
import CancellationToken from 'cancellationtoken'; import { Channel, ChannelClass } from './Channel'; import { ChannelOptions } from './ChannelOptions'; import { ControlCode } from './ControlCode'; import { Deferred } from './Deferred'; import { FrameHeader } from './FrameHeader'; import { IChannelOfferEventArgs } from './IChannelOfferEventArgs'; import { IDisposableObservable } from './IDisposableObservable'; import { MultiplexingStreamFormatter } from './MultiplexingStreamFormatters'; import './MultiplexingStreamOptions'; import { MultiplexingStreamOptions } from './MultiplexingStreamOptions'; import { QualifiedChannelId } from './QualifiedChannelId'; export declare abstract class MultiplexingStream implements IDisposableObservable { protected readonly formatter: MultiplexingStreamFormatter; private readonly isOdd; /** * The maximum length of a frame's payload. */ static readonly framePayloadMaxLength: number; private static readonly recommendedDefaultChannelReceivingWindowSize; /** The default window size used for new channels that do not specify a value for ChannelOptions.ChannelReceivingWindowSize. */ readonly defaultChannelReceivingWindowSize: number; protected get disposalToken(): CancellationToken; /** * Gets a promise that is resolved or rejected based on how this stream is disposed or fails. */ get completion(): Promise<void>; /** * Gets a value indicating whether this instance has been disposed. */ get isDisposed(): boolean; /** * Initializes a new instance of the `MultiplexingStream` class. * @param stream The duplex stream to read and write to. * Use `FullDuplexStream.Splice` if you have distinct input/output streams. * @param options Options to customize the behavior of the stream. * @param cancellationToken A token whose cancellation aborts the handshake with the remote end. * @returns The multiplexing stream, once the handshake is complete. */ static CreateAsync(stream: NodeJS.ReadWriteStream, options?: MultiplexingStreamOptions, cancellationToken?: CancellationToken): Promise<MultiplexingStream>; /** * Initializes a new instance of the `MultiplexingStream` class * with protocolMajorVersion set to 3. * @param stream The duplex stream to read and write to. * Use `FullDuplexStream.Splice` if you have distinct input/output streams. * @param options Options to customize the behavior of the stream. * @returns The multiplexing stream. */ static Create(stream: NodeJS.ReadWriteStream, options?: MultiplexingStreamOptions): MultiplexingStream; /** * The options to use for channels we create in response to incoming offers. * @description Whatever these settings are, they can be replaced when the channel is accepted. */ protected static readonly defaultChannelOptions: ChannelOptions; /** * The encoding used for characters in control frames. */ static readonly ControlFrameEncoding = "utf-8"; protected readonly _completionSource: Deferred<void>; /** * A dictionary of channels that were seeded, keyed by their ID. */ protected readonly seededOpenChannels: { [id: number]: ChannelClass; }; /** * A dictionary of channels that were offered locally, keyed by their ID. */ protected readonly locallyOfferedOpenChannels: { [id: number]: ChannelClass; }; /** * A dictionary of channels that were offered remotely, keyed by their ID. */ protected readonly remotelyOfferedOpenChannels: { [id: number]: ChannelClass; }; /** * The last number assigned to a channel. * Each use of this should increment by two if isOdd is defined. * It should never exceed uint32.MaxValue */ protected abstract lastOfferedChannelId: number; /** * A map of channel names to queues of channels waiting for local acceptance. */ protected readonly channelsOfferedByThemByName: { [name: string]: ChannelClass[]; }; /** * A map of channel names to queues of Deferred<Channel> from waiting accepters. */ protected readonly acceptingChannels: { [name: string]: Deferred<ChannelClass>[]; }; /** The major version of the protocol being used for this connection. */ protected readonly protocolMajorVersion: number; private readonly eventEmitter; private disposalTokenSource; protected constructor(formatter: MultiplexingStreamFormatter, isOdd: boolean | undefined, options: MultiplexingStreamOptions); /** * Creates an anonymous channel that may be accepted by <see cref="AcceptChannel(int, ChannelOptions)"/>. * Its existance must be communicated by other means (typically another, existing channel) to encourage acceptance. * @param options A set of options that describe local treatment of this channel. * @returns The anonymous channel. * @description Note that while the channel is created immediately, any local write to that channel will be * buffered locally until the remote party accepts the channel. */ createChannel(options?: ChannelOptions): Channel; /** * Accepts a channel with a specific ID. * @param id The id of the channel to accept. * @param options A set of options that describe local treatment of this channel. * @description This method can be used to accept anonymous channels created with <see cref="CreateChannel"/>. * Unlike <see cref="AcceptChannelAsync(string, ChannelOptions, CancellationToken)"/> which will await * for a channel offer if a matching one has not been made yet, this method only accepts an offer * for a channel that has already been made. */ acceptChannel(id: number, options?: ChannelOptions): Channel; /** * Rejects an offer for the channel with a specified ID. * @param id The ID of the channel whose offer should be rejected. */ rejectChannel(id: number): void; /** * Offers a new, named channel to the remote party so they may accept it with * {@link acceptChannelAsync}. * @param name A name for the channel, which must be accepted on the remote end to complete creation. * It need not be unique, and may be empty but must not be null. * Any characters are allowed, and max length is determined by the maximum frame payload (based on UTF-8 encoding). * @param options A set of options that describe local treatment of this channel. * @param cancellationToken A cancellation token. Do NOT let this be a long-lived token * or a memory leak will result since we add continuations to its promise. * @returns A task that completes with the `Channel` if the offer is accepted on the remote end * or faults with `MultiplexingProtocolException` if the remote end rejects the channel. */ offerChannelAsync(name: string, options?: ChannelOptions, cancellationToken?: CancellationToken): Promise<Channel>; /** * Accepts a channel that the remote end has attempted or may attempt to create. * @param name The name of the channel to accept. * An empty string will match an offer made via {@link offerChannelAsync} with an empty channel name. * It will also match an anonymous channel offer made with {@link createChannel}. * @param options A set of options that describe local treatment of this channel. * @param cancellationToken A token to indicate lost interest in accepting the channel. * Do NOT let this be a long-lived token * or a memory leak will result since we add continuations to its promise. * @returns The `Channel`, after its offer has been received from the remote party and accepted. * @description If multiple offers exist with the specified `name`, the first one received will be accepted. */ acceptChannelAsync(name: string, options?: ChannelOptions, cancellationToken?: CancellationToken): Promise<Channel>; /** * Disposes the stream. */ dispose(): void; protected disposeCore(remoteDisconnect: boolean): void; on(event: 'channelOffered', listener: (args: IChannelOfferEventArgs) => void): void; off(event: 'channelOffered', listener: (args: IChannelOfferEventArgs) => void): void; once(event: 'channelOffered', listener: (args: IChannelOfferEventArgs) => void): void; protected raiseChannelOffered(id: number, name: string, isAccepted: boolean): void; protected abstract sendFrameAsync(header: FrameHeader, payload: Buffer, cancellationToken: CancellationToken): Promise<void>; protected abstract sendFrame(code: ControlCode, channelId: QualifiedChannelId): Promise<void>; protected acceptChannelOrThrow(channel: ChannelClass, options?: ChannelOptions): void; /** * Disposes this instance if the specified promise is rejected. * @param promise The promise to check for failures. */ protected rejectOnFailure<T>(promise: Promise<T>): Promise<void>; protected removeChannelFromOfferedQueue(channel: ChannelClass): void; protected getOpenChannel(qualifiedId: QualifiedChannelId): ChannelClass | undefined; protected setOpenChannel(channel: ChannelClass): void; protected deleteOpenChannel(qualifiedId: QualifiedChannelId): void; private getChannelCollection; /** * Cancels a prior call to acceptChannelAsync * @param channel The promise of a channel to be canceled. * @param name The name of the channel the caller was accepting. * @param reason The reason for cancellation. */ private acceptChannelCanceled; /** * Responds to cancellation of a prior call to offerChannelAsync. * @param channel The channel previously offered. */ private offerChannelCanceled; /** * Gets a unique number that can be used to represent a channel. * @description The channel numbers increase by two in order to maintain odd or even numbers, * since each party is allowed to create only one or the other. */ private getUnusedChannelId; } export declare class MultiplexingStreamClass extends MultiplexingStream { protected lastOfferedChannelId: number; private readonly sendingSemaphore; constructor(formatter: MultiplexingStreamFormatter, isOdd: boolean | undefined, options: MultiplexingStreamOptions); get backpressureSupportEnabled(): boolean; sendFrameAsync(header: FrameHeader, payload?: Buffer, cancellationToken?: CancellationToken): Promise<void>; /** * Transmits a frame over the stream. * @param code The op code for the channel. * @param channelId The ID of the channel to receive the frame. * @description The promise returned from this function is always resolved (not rejected) * since it is anticipated that callers may not be awaiting its result. */ sendFrame(code: ControlCode, channelId: QualifiedChannelId): Promise<void>; onChannelWritingCompleted(channel: ChannelClass): void; onChannelDisposed(channel: ChannelClass, error: Error | null): Promise<void>; localContentExamined(channel: ChannelClass, bytesConsumed: number): void; private readFromStream; private onOffer; private onOfferAccepted; private onContent; private onContentProcessed; private onContentWritingCompleted; /** * Occurs when the remote party has terminated a channel (including canceling an offer). * @param channelId The ID of the terminated channel. */ private onChannelTerminated; }