Skip to content

Commit

Permalink
Implement makeTunnel for localhost
Browse files Browse the repository at this point in the history
Part of #81388
  • Loading branch information
alexr00 committed Dec 11, 2019
1 parent c4198fa commit 15c35f5
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/vs/platform/remote/common/tunnel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ export const ITunnelService = createDecorator<ITunnelService>('tunnelService');

export interface RemoteTunnel {
readonly tunnelRemotePort: number;
readonly tunnelRemoteHost: string;
readonly tunnelLocalPort: number;
readonly localAddress?: string;
readonly localAddress: string;
dispose(): void;
}

Expand Down
7 changes: 3 additions & 4 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ declare module 'vscode' {
remote: { port: number, host: string };
localPort?: number;
name?: string;
closeable?: boolean;
}

export interface Tunnel extends Disposable {
remote: { port: number, host: string };
local: { port: number, host: string };
localAddress: string;
}

/**
Expand All @@ -54,7 +53,7 @@ declare module 'vscode' {
* 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?: { remotePort: number, localAddress: string }[];
detectedTunnels?: { remote: { port: number, host: string }, localAddress: string }[];
}

export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation;
Expand All @@ -78,7 +77,7 @@ declare module 'vscode' {

export namespace workspace {
/**
* Forwards a port.
* Forwards a port. Currently only works for a remote host of localhost.
* @param forward The `localPort` is a suggestion only. If that port is not available another will be chosen.
*/
export function makeTunnel(forward: TunnelOptions): Thenable<Tunnel>;
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/browser/extensionHost.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import './mainThreadWorkspace';
import './mainThreadComments';
import './mainThreadTask';
import './mainThreadLabelService';
import './mainThreadTunnelService';
import 'vs/workbench/api/common/apiCommands';

export class ExtensionPoints implements IWorkbenchContribution {
Expand Down
38 changes: 38 additions & 0 deletions src/vs/workbench/api/browser/mainThreadTunnelService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* 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 { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';

@extHostNamedCustomer(MainContext.MainThreadTunnelService)
export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
// @ts-ignore
private readonly _proxy: ExtHostTunnelServiceShape;

constructor(
extHostContext: IExtHostContext,
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTunnelService);
}

async $openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined> {
const tunnel = await this.remoteExplorerService.tunnelModel.forward(tunnelOptions.remote.port, tunnelOptions.localPort, tunnelOptions.name);
if (tunnel) {
return { remote: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress };
}
return undefined;
}

async $closeTunnel(remotePort: number): Promise<void> {
return this.remoteExplorerService.tunnelModel.close(remotePort);
}

dispose(): void {
//
}
}
9 changes: 8 additions & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ 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';

export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
Expand Down Expand Up @@ -776,6 +777,11 @@ export interface MainThreadWindowShape extends IDisposable {
$asExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise<UriComponents>;
}

export interface MainThreadTunnelServiceShape extends IDisposable {
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
$closeTunnel(remotePort: number): Promise<void>;
}

// -- extension host

export interface ExtHostCommandsShape {
Expand Down Expand Up @@ -1435,7 +1441,8 @@ export const MainContext = {
MainThreadSearch: createMainId<MainThreadSearchShape>('MainThreadSearch'),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService')
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService'),
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService')
};

export const ExtHostContext = {
Expand Down
47 changes: 41 additions & 6 deletions src/vs/workbench/api/common/extHostTunnelService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,54 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
import * as vscode from 'vscode';
import { ExtHostTunnelServiceShape, MainThreadTunnelServiceShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import * as vscode from 'vscode';
import { Disposable } 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 };
localAddress: string;
}

export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
makeTunnel(forward: vscode.TunnelOptions): Promise<vscode.Tunnel>;
makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
}

export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IExtHostTunnelService');

export class ExtHostTunnelService implements IExtHostTunnelService {
makeTunnel(forward: vscode.TunnelOptions): Promise<vscode.Tunnel> {
throw new Error('Method not implemented.');

export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService {
private readonly _proxy: MainThreadTunnelServiceShape;

constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService
) {
super();
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTunnelService);
}
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
const tunnel = await this._proxy.$openTunnel(forward);
if (tunnel) {
const disposableTunnel: vscode.Tunnel = {
remote: tunnel.remote,
localAddress: tunnel.localAddress,
dispose: () => {
return this._proxy.$closeTunnel(tunnel.remote.port);
}
};
this._register(disposableTunnel);
return disposableTunnel;
}
return undefined;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ITunnelService } from 'vs/platform/remote/common/tunnel';
import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
import { Disposable } from 'vs/base/common/lifecycle';
import { IEditableData } from 'vs/workbench/common/views';

Expand Down Expand Up @@ -63,7 +63,8 @@ export class TunnelModel extends Disposable {
this.forwarded.set(tunnel.tunnelRemotePort, {
remote: tunnel.tunnelRemotePort,
localAddress: tunnel.localAddress,
local: tunnel.tunnelLocalPort
local: tunnel.tunnelLocalPort,
closeable: true
});
}
this._onForwardPort.fire(this.forwarded.get(tunnel.tunnelRemotePort)!);
Expand All @@ -76,7 +77,7 @@ export class TunnelModel extends Disposable {
}));
}

async forward(remote: number, local?: number, name?: string): Promise<void> {
async forward(remote: number, local?: number, name?: string): Promise<RemoteTunnel | void> {
if (!this.forwarded.has(remote)) {
const tunnel = await this.tunnelService.openTunnel(remote, local);
if (tunnel && tunnel.localAddress) {
Expand All @@ -89,6 +90,7 @@ export class TunnelModel extends Disposable {
};
this.forwarded.set(remote, newForward);
this._onForwardPort.fire(newForward);
return tunnel;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/services/remote/node/tunnelService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel {

public readonly tunnelRemotePort: number;
public tunnelLocalPort!: number;
public localAddress?: string;
public tunnelRemoteHost: string = 'localhost';
public localAddress!: string;

private readonly _options: IConnectionOptions;
private readonly _server: net.Server;
Expand Down Expand Up @@ -145,6 +146,7 @@ export class TunnelService implements ITunnelService {
private makeTunnel(tunnel: RemoteTunnel): RemoteTunnel {
return {
tunnelRemotePort: tunnel.tunnelRemotePort,
tunnelRemoteHost: tunnel.tunnelRemoteHost,
tunnelLocalPort: tunnel.tunnelLocalPort,
localAddress: tunnel.localAddress,
dispose: () => {
Expand Down

0 comments on commit 15c35f5

Please sign in to comment.