diff --git a/src/vs/platform/remote/common/remoteAuthorityResolver.ts b/src/vs/platform/remote/common/remoteAuthorityResolver.ts index 8d0e2617a34..7cd49599314 100644 --- a/src/vs/platform/remote/common/remoteAuthorityResolver.ts +++ b/src/vs/platform/remote/common/remoteAuthorityResolver.ts @@ -18,7 +18,7 @@ export interface ResolvedOptions { } export interface TunnelInformation { - detectedTunnels?: { remote: { port: number, host: string }, localAddress: string }[]; + environmentTunnels?: { remoteAddress: { port: number, host: string }, localAddress: string }[]; } export interface ResolverResult { diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index b5fdfa8bff0..154df6e884e 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -19,9 +19,9 @@ export interface RemoteTunnel { } export interface TunnelOptions { - remote: { port: number, host: string }; + remoteAddress: { port: number, host: string }; localPort?: number; - name?: string; + label?: string; } export interface ITunnelProvider { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index ad7d468f6fb..5102240dd8a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -34,15 +34,18 @@ declare module 'vscode' { } export interface TunnelOptions { - remote: { port: number, host: string }; - localPort?: number; - name?: string; + remoteAddress: { port: number, host: string }; + // The desired local port. If this port can't be used, then another will be chosen. + localAddressPort?: number; + label?: string; } export interface Tunnel { - remote: { port: number, host: string }; + remoteAddress: { port: number, host: string }; + //The complete local address(ex. localhost:1234) localAddress: string; - onDispose: Event; + // Implementers of Tunnel should fire onDidDispose when dispose is called. + onDidDispose: Event; dispose(): void; } @@ -52,10 +55,10 @@ declare module 'vscode' { export interface TunnelInformation { /** * Tunnels that are detected by the extension. The remotePort is used for display purposes. - * The localAddress should be the complete local address(ex. localhost:1234) for connecting to the port. Tunnels provided through + * The localAddress should be the complete local address (ex. localhost:1234) for connecting to the port. Tunnels provided through * detected are read-only from the forwarded ports UI. */ - detectedTunnels?: { remote: { port: number, host: string }, localAddress: string }[]; + environmentTunnels?: { remoteAddress: { port: number, host: string }, localAddress: string }[]; } export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; @@ -74,16 +77,16 @@ declare module 'vscode' { * When not implemented, the core will use its default forwarding logic. * When implemented, the core will use this to forward ports. */ - forwardPort?(tunnelOptions: TunnelOptions): Thenable | undefined; + tunnelFactory?: (tunnelOptions: TunnelOptions) => Thenable | undefined; } export namespace workspace { /** * Forwards a port. If the current resolver implements RemoteAuthorityResolver:forwardPort then that will be used to make the tunnel. - * By default, makeTunnel only support localhost; however, RemoteAuthorityResolver:forwardPort can be used to support other ips. - * @param forward The `localPort` is a suggestion only. If that port is not available another will be chosen. + * By default, openTunnel only support localhost; however, RemoteAuthorityResolver:tunnelFactory can be used to support other ips. + * @param tunnelOptions The `localPort` is a suggestion only. If that port is not available another will be chosen. */ - export function makeTunnel(forward: TunnelOptions): Thenable; + export function openTunnel(tunnelOptions: TunnelOptions): Thenable; } export interface ResourceLabelFormatter { diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index 3ab437aeef4..2a1b63a6f32 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostContext, ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; -import { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; +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 } from 'vs/platform/remote/common/tunnel'; +import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel'; @extHostNamedCustomer(MainContext.MainThreadTunnelService) export class MainThreadTunnelService implements MainThreadTunnelServiceShape { @@ -22,7 +22,7 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape { } async $openTunnel(tunnelOptions: TunnelOptions): Promise { - const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remote, tunnelOptions.localPort, tunnelOptions.name); + const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localPort, tunnelOptions.label); if (tunnel) { return TunnelDto.fromServiceTunnel(tunnel); } @@ -44,11 +44,11 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape { if (forward) { return forward.then(tunnel => { return { - tunnelRemotePort: tunnel.remote.port, - tunnelRemoteHost: tunnel.remote.host, + tunnelRemotePort: tunnel.remoteAddress.port, + tunnelRemoteHost: tunnel.remoteAddress.host, localAddress: tunnel.localAddress, dispose: () => { - this._proxy.$closeTunnel({ host: tunnel.remote.host, port: tunnel.remote.port }); + this._proxy.$closeTunnel({ host: tunnel.remoteAddress.host, port: tunnel.remoteAddress.port }); } }; }); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b0466c7c142..95470c9d94b 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -714,9 +714,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I onWillRenameFiles: (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => { return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables); }, - makeTunnel: (forward: vscode.TunnelOptions) => { + openTunnel: (forward: vscode.TunnelOptions) => { checkProposedApiEnabled(extension); - return extHostTunnelService.makeTunnel(forward); + return extHostTunnelService.openTunnel(forward); } }; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b4c6ebbb625..2aac272c570 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -47,7 +47,8 @@ import { createExtHostContextProxyIdentifier as createExtId, createMainContextPr import * as search from 'vs/workbench/services/search/common/search'; import { SaveReason } from 'vs/workbench/common/editor'; import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; -import { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; +import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; +import { TunnelOptions } from 'vs/platform/remote/common/tunnel'; export interface IEnvironment { isExtensionDevelopmentDebug: boolean; diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index caa8fee5d81..944546d61d9 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -662,7 +662,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio value: { authority, options, - tunnelInformation: { detectedTunnels: result.detectedTunnels } + tunnelInformation: { environmentTunnels: result.environmentTunnels } } }; } catch (err) { diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index a606b3820f0..f3e81eab7bd 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -6,27 +6,20 @@ import { ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import * as vscode from 'vscode'; -import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; +import { RemoteTunnel, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { IDisposable } from 'vs/base/common/lifecycle'; -export interface TunnelOptions { - remote: { port: number, host: string }; - localPort?: number; - name?: string; - closeable?: boolean; -} - export interface TunnelDto { - remote: { port: number, host: string }; + remoteAddress: { port: number, host: string }; localAddress: string; } export namespace TunnelDto { export function fromApiTunnel(tunnel: vscode.Tunnel): TunnelDto { - return { remote: tunnel.remote, localAddress: tunnel.localAddress }; + return { remoteAddress: tunnel.remoteAddress, localAddress: tunnel.localAddress }; } export function fromServiceTunnel(tunnel: RemoteTunnel): TunnelDto { - return { remote: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress }; + return { remoteAddress: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress }; } } @@ -37,7 +30,7 @@ export interface Tunnel extends vscode.Disposable { export interface IExtHostTunnelService extends ExtHostTunnelServiceShape { readonly _serviceBrand: undefined; - makeTunnel(forward: TunnelOptions): Promise; + openTunnel(forward: TunnelOptions): Promise; setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise; } @@ -45,7 +38,7 @@ export const IExtHostTunnelService = createDecorator('IEx export class ExtHostTunnelService implements IExtHostTunnelService { _serviceBrand: undefined; - async makeTunnel(forward: TunnelOptions): Promise { + async openTunnel(forward: TunnelOptions): Promise { return undefined; } async $findCandidatePorts(): Promise<{ host: string, port: number; detail: string; }[]> { diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 93b333980a5..ee35a7d80b0 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -13,16 +13,17 @@ import { exec } from 'child_process'; import * as resources from 'vs/base/common/resources'; import * as fs from 'fs'; import { isLinux } from 'vs/base/common/platform'; -import { IExtHostTunnelService, TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; +import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { asPromise } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; +import { TunnelOptions } from 'vs/platform/remote/common/tunnel'; class ExtensionTunnel implements vscode.Tunnel { private _onDispose: Emitter = new Emitter(); - onDispose: Event = this._onDispose.event; + onDidDispose: Event = this._onDispose.event; constructor( - public readonly remote: { port: number; host: string; }, + public readonly remoteAddress: { port: number; host: string; }, public readonly localAddress: string, private readonly _dispose: () => void) { } @@ -48,11 +49,11 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe this.registerCandidateFinder(); } } - async makeTunnel(forward: TunnelOptions): Promise { + async openTunnel(forward: TunnelOptions): Promise { const tunnel = await this._proxy.$openTunnel(forward); if (tunnel) { - const disposableTunnel: vscode.Tunnel = new ExtensionTunnel(tunnel.remote, tunnel.localAddress, () => { - return this._proxy.$closeTunnel(tunnel.remote); + const disposableTunnel: vscode.Tunnel = new ExtensionTunnel(tunnel.remoteAddress, tunnel.localAddress, () => { + return this._proxy.$closeTunnel(tunnel.remoteAddress); }); this._register(disposableTunnel); return disposableTunnel; @@ -65,8 +66,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe } async setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise { - if (provider && provider.forwardPort) { - this._forwardPortProvider = provider.forwardPort; + if (provider && provider.tunnelFactory) { + this._forwardPortProvider = provider.tunnelFactory; await this._proxy.$setTunnelProvider(); } else { this._forwardPortProvider = undefined; @@ -91,11 +92,11 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe const providedPort = this._forwardPortProvider!(tunnelOptions); if (providedPort !== undefined) { return asPromise(() => providedPort).then(tunnel => { - if (!this._extensionTunnels.has(tunnelOptions.remote.host)) { - this._extensionTunnels.set(tunnelOptions.remote.host, new Map()); + if (!this._extensionTunnels.has(tunnelOptions.remoteAddress.host)) { + this._extensionTunnels.set(tunnelOptions.remoteAddress.host, new Map()); } - this._extensionTunnels.get(tunnelOptions.remote.host)!.set(tunnelOptions.remote.port, tunnel); - this._register(tunnel.onDispose(() => this._proxy.$closeTunnel(tunnel.remote))); + this._extensionTunnels.get(tunnelOptions.remoteAddress.host)!.set(tunnelOptions.remoteAddress.port, tunnel); + this._register(tunnel.onDidDispose(() => this._proxy.$closeTunnel(tunnel.remoteAddress))); return Promise.resolve(TunnelDto.fromApiTunnel(tunnel)); }); } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 0ca576029c4..04b014914bb 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -473,7 +473,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten // set the resolved authority this._remoteAuthorityResolverService.setResolvedAuthority(resolvedAuthority.authority, resolvedAuthority.options); - this._remoteExplorerService.addDetected(resolvedAuthority.tunnelInformation?.detectedTunnels); + this._remoteExplorerService.addEnvironmentTunnels(resolvedAuthority.tunnelInformation?.environmentTunnels); // monitor for breakage const connection = this._remoteAgentService.getConnection(); diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 6dc3baf25dc..7453c0297d4 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -152,11 +152,11 @@ export class TunnelModel extends Disposable { return (this.forwarded.get(key) || this.detected.get(key))?.localAddress; } - addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[]): void { + addEnvironmentTunnels(tunnels: { remoteAddress: { port: number, host: string }, localAddress: string }[]): void { tunnels.forEach(tunnel => { - this.detected.set(MakeAddress(tunnel.remote.host, tunnel.remote.port), { - remoteHost: tunnel.remote.host, - remotePort: tunnel.remote.port, + this.detected.set(MakeAddress(tunnel.remoteAddress.host, tunnel.remoteAddress.port), { + remoteHost: tunnel.remoteAddress.host, + remotePort: tunnel.remoteAddress.port, localAddress: tunnel.localAddress, closeable: false }); @@ -186,7 +186,7 @@ export interface IRemoteExplorerService { getEditableData(remoteHost: string | undefined, remotePort: number | undefined): IEditableData | undefined; forward(remote: { host: string, port: number }, localPort?: number, name?: string): Promise; close(remote: { host: string, port: number }): Promise; - addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): void; + addEnvironmentTunnels(tunnels: { remoteAddress: { port: number, host: string }, localAddress: string }[] | undefined): void; registerCandidateFinder(finder: () => Promise<{ host: string, port: number, detail: string }[]>): void; } @@ -299,9 +299,9 @@ class RemoteExplorerService implements IRemoteExplorerService { return this.tunnelModel.close(remote.host, remote.port); } - addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): void { + addEnvironmentTunnels(tunnels: { remoteAddress: { port: number, host: string }, localAddress: string }[] | undefined): void { if (tunnels) { - this.tunnelModel.addDetected(tunnels); + this.tunnelModel.addEnvironmentTunnels(tunnels); } } diff --git a/src/vs/workbench/services/remote/node/tunnelService.ts b/src/vs/workbench/services/remote/node/tunnelService.ts index 79f473813dc..66e50c7e997 100644 --- a/src/vs/workbench/services/remote/node/tunnelService.ts +++ b/src/vs/workbench/services/remote/node/tunnelService.ts @@ -224,7 +224,7 @@ export class TunnelService implements ITunnelService { } if (this._tunnelProvider) { - const tunnel = this._tunnelProvider.forwardPort({ remote: { host: remoteHost, port: remotePort } }); + const tunnel = this._tunnelProvider.forwardPort({ remoteAddress: { host: remoteHost, port: remotePort } }); if (tunnel) { this.addTunnelToMap(remoteHost, remotePort, tunnel); }