|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { CallCredentials } from './call-credentials'; |
|
import { Status } from './constants'; |
|
import { Deadline } from './deadline'; |
|
import { Metadata } from './metadata'; |
|
import { ServerSurfaceCall } from './server-call'; |
|
|
|
export interface CallStreamOptions { |
|
deadline: Deadline; |
|
flags: number; |
|
host: string; |
|
parentCall: ServerSurfaceCall | null; |
|
} |
|
|
|
export type PartialCallStreamOptions = Partial<CallStreamOptions>; |
|
|
|
export interface StatusObject { |
|
code: Status; |
|
details: string; |
|
metadata: Metadata; |
|
} |
|
|
|
export type PartialStatusObject = Pick<StatusObject, 'code' | 'details'> & { |
|
metadata: Metadata | null; |
|
}; |
|
|
|
export const enum WriteFlags { |
|
BufferHint = 1, |
|
NoCompress = 2, |
|
WriteThrough = 4, |
|
} |
|
|
|
export interface WriteObject { |
|
message: Buffer; |
|
flags?: number; |
|
} |
|
|
|
export interface MetadataListener { |
|
(metadata: Metadata, next: (metadata: Metadata) => void): void; |
|
} |
|
|
|
export interface MessageListener { |
|
|
|
(message: any, next: (message: any) => void): void; |
|
} |
|
|
|
export interface StatusListener { |
|
(status: StatusObject, next: (status: StatusObject) => void): void; |
|
} |
|
|
|
export interface FullListener { |
|
onReceiveMetadata: MetadataListener; |
|
onReceiveMessage: MessageListener; |
|
onReceiveStatus: StatusListener; |
|
} |
|
|
|
export type Listener = Partial<FullListener>; |
|
|
|
|
|
|
|
|
|
export interface InterceptingListener { |
|
onReceiveMetadata(metadata: Metadata): void; |
|
|
|
onReceiveMessage(message: any): void; |
|
onReceiveStatus(status: StatusObject): void; |
|
} |
|
|
|
export function isInterceptingListener( |
|
listener: Listener | InterceptingListener |
|
): listener is InterceptingListener { |
|
return ( |
|
listener.onReceiveMetadata !== undefined && |
|
listener.onReceiveMetadata.length === 1 |
|
); |
|
} |
|
|
|
export class InterceptingListenerImpl implements InterceptingListener { |
|
private processingMetadata = false; |
|
private hasPendingMessage = false; |
|
private pendingMessage: any; |
|
private processingMessage = false; |
|
private pendingStatus: StatusObject | null = null; |
|
constructor( |
|
private listener: FullListener, |
|
private nextListener: InterceptingListener |
|
) {} |
|
|
|
private processPendingMessage() { |
|
if (this.hasPendingMessage) { |
|
this.nextListener.onReceiveMessage(this.pendingMessage); |
|
this.pendingMessage = null; |
|
this.hasPendingMessage = false; |
|
} |
|
} |
|
|
|
private processPendingStatus() { |
|
if (this.pendingStatus) { |
|
this.nextListener.onReceiveStatus(this.pendingStatus); |
|
} |
|
} |
|
|
|
onReceiveMetadata(metadata: Metadata): void { |
|
this.processingMetadata = true; |
|
this.listener.onReceiveMetadata(metadata, metadata => { |
|
this.processingMetadata = false; |
|
this.nextListener.onReceiveMetadata(metadata); |
|
this.processPendingMessage(); |
|
this.processPendingStatus(); |
|
}); |
|
} |
|
|
|
onReceiveMessage(message: any): void { |
|
|
|
|
|
this.processingMessage = true; |
|
this.listener.onReceiveMessage(message, msg => { |
|
this.processingMessage = false; |
|
if (this.processingMetadata) { |
|
this.pendingMessage = msg; |
|
this.hasPendingMessage = true; |
|
} else { |
|
this.nextListener.onReceiveMessage(msg); |
|
this.processPendingStatus(); |
|
} |
|
}); |
|
} |
|
onReceiveStatus(status: StatusObject): void { |
|
this.listener.onReceiveStatus(status, processedStatus => { |
|
if (this.processingMetadata || this.processingMessage) { |
|
this.pendingStatus = processedStatus; |
|
} else { |
|
this.nextListener.onReceiveStatus(processedStatus); |
|
} |
|
}); |
|
} |
|
} |
|
|
|
export interface WriteCallback { |
|
(error?: Error | null): void; |
|
} |
|
|
|
export interface MessageContext { |
|
callback?: WriteCallback; |
|
flags?: number; |
|
} |
|
|
|
export interface Call { |
|
cancelWithStatus(status: Status, details: string): void; |
|
getPeer(): string; |
|
start(metadata: Metadata, listener: InterceptingListener): void; |
|
sendMessageWithContext(context: MessageContext, message: Buffer): void; |
|
startRead(): void; |
|
halfClose(): void; |
|
getCallNumber(): number; |
|
setCredentials(credentials: CallCredentials): void; |
|
} |
|
|