Path: blob/main/src/vs/workbench/api/browser/mainThreadManagedSockets.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { VSBuffer } from '../../../base/common/buffer.js';6import { Emitter } from '../../../base/common/event.js';7import { Disposable, IDisposable } from '../../../base/common/lifecycle.js';8import { ISocket, SocketCloseEventType } from '../../../base/parts/ipc/common/ipc.net.js';9import { ManagedSocket, RemoteSocketHalf, connectManagedSocket } from '../../../platform/remote/common/managedSocket.js';10import { ManagedRemoteConnection, RemoteConnectionType } from '../../../platform/remote/common/remoteAuthorityResolver.js';11import { IRemoteSocketFactoryService, ISocketFactory } from '../../../platform/remote/common/remoteSocketFactoryService.js';12import { ExtHostContext, ExtHostManagedSocketsShape, MainContext, MainThreadManagedSocketsShape } from '../common/extHost.protocol.js';13import { IExtHostContext, extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';1415@extHostNamedCustomer(MainContext.MainThreadManagedSockets)16export class MainThreadManagedSockets extends Disposable implements MainThreadManagedSocketsShape {1718private readonly _proxy: ExtHostManagedSocketsShape;19private readonly _registrations = new Map<number, IDisposable>();20private readonly _remoteSockets = new Map<number, RemoteSocketHalf>();2122constructor(23extHostContext: IExtHostContext,24@IRemoteSocketFactoryService private readonly _remoteSocketFactoryService: IRemoteSocketFactoryService,25) {26super();27this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostManagedSockets);28}2930async $registerSocketFactory(socketFactoryId: number): Promise<void> {31const that = this;32const socketFactory = new class implements ISocketFactory<RemoteConnectionType.Managed> {3334supports(connectTo: ManagedRemoteConnection): boolean {35return (connectTo.id === socketFactoryId);36}3738connect(connectTo: ManagedRemoteConnection, path: string, query: string, debugLabel: string): Promise<ISocket> {39return new Promise<ISocket>((resolve, reject) => {40if (connectTo.id !== socketFactoryId) {41return reject(new Error('Invalid connectTo'));42}4344const factoryId = connectTo.id;45that._proxy.$openRemoteSocket(factoryId).then(socketId => {46const half: RemoteSocketHalf = {47onClose: new Emitter(),48onData: new Emitter(),49onEnd: new Emitter(),50};51that._remoteSockets.set(socketId, half);5253MainThreadManagedSocket.connect(socketId, that._proxy, path, query, debugLabel, half)54.then(55socket => {56socket.onDidDispose(() => that._remoteSockets.delete(socketId));57resolve(socket);58},59err => {60that._remoteSockets.delete(socketId);61reject(err);62});63}).catch(reject);64});65}66};67this._registrations.set(socketFactoryId, this._remoteSocketFactoryService.register(RemoteConnectionType.Managed, socketFactory));6869}7071async $unregisterSocketFactory(socketFactoryId: number): Promise<void> {72this._registrations.get(socketFactoryId)?.dispose();73}7475$onDidManagedSocketHaveData(socketId: number, data: VSBuffer): void {76this._remoteSockets.get(socketId)?.onData.fire(data);77}7879$onDidManagedSocketClose(socketId: number, error: string | undefined): void {80this._remoteSockets.get(socketId)?.onClose.fire({81type: SocketCloseEventType.NodeSocketCloseEvent,82error: error ? new Error(error) : undefined,83hadError: !!error84});85this._remoteSockets.delete(socketId);86}8788$onDidManagedSocketEnd(socketId: number): void {89this._remoteSockets.get(socketId)?.onEnd.fire();90}91}9293export class MainThreadManagedSocket extends ManagedSocket {94public static connect(95socketId: number,96proxy: ExtHostManagedSocketsShape,97path: string, query: string, debugLabel: string,98half: RemoteSocketHalf99): Promise<MainThreadManagedSocket> {100const socket = new MainThreadManagedSocket(socketId, proxy, debugLabel, half);101return connectManagedSocket(socket, path, query, debugLabel, half);102}103104private constructor(105private readonly socketId: number,106private readonly proxy: ExtHostManagedSocketsShape,107debugLabel: string,108half: RemoteSocketHalf,109) {110super(debugLabel, half);111}112113public override write(buffer: VSBuffer): void {114this.proxy.$remoteSocketWrite(this.socketId, buffer);115}116117protected override closeRemote(): void {118this.proxy.$remoteSocketEnd(this.socketId);119}120121public override drain(): Promise<void> {122return this.proxy.$remoteSocketDrain(this.socketId);123}124}125126127