/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostContext, ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; @extHostNamedCustomer(MainContext.MainThreadTunnelService) export class MainThreadTunnelService extends Disposable implements MainThreadTunnelServiceShape { private readonly _proxy: ExtHostTunnelServiceShape; constructor( extHostContext: IExtHostContext, @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, @ITunnelService private readonly tunnelService: ITunnelService ) { super(); this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTunnelService); } async $openTunnel(tunnelOptions: TunnelOptions): Promise { const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label); if (tunnel) { return TunnelDto.fromServiceTunnel(tunnel); } return undefined; } async $closeTunnel(remote: { host: string, port: number }): Promise { return this.remoteExplorerService.close(remote); } async $registerCandidateFinder(): Promise { this.remoteExplorerService.registerCandidateFinder(() => this._proxy.$findCandidatePorts()); } async $setTunnelProvider(): Promise { const tunnelProvider: ITunnelProvider = { forwardPort: (tunnelOptions: TunnelOptions) => { const forward = this._proxy.$forwardPort(tunnelOptions); if (forward) { return forward.then(tunnel => { return { tunnelRemotePort: tunnel.remoteAddress.port, tunnelRemoteHost: tunnel.remoteAddress.host, localAddress: tunnel.localAddress, dispose: () => { this._proxy.$closeTunnel({ host: tunnel.remoteAddress.host, port: tunnel.remoteAddress.port }); } }; }); } return undefined; } }; this.tunnelService.setTunnelProvider(tunnelProvider); } async $setCandidateFilter(): Promise { this._register(this.remoteExplorerService.setCandidateFilter(async (candidates: { host: string, port: number, detail: string }[]): Promise<{ host: string, port: number, detail: string }[]> => { const filters: boolean[] = await this._proxy.$filterCandidates(candidates); const filteredCandidates: { host: string, port: number, detail: string }[] = []; if (filters.length !== candidates.length) { return candidates; } for (let i = 0; i < candidates.length; i++) { if (filters[i]) { filteredCandidates.push(candidates[i]); } } return filteredCandidates; })); } dispose(): void { } }