Skip to content

Commit ec64531

Browse files
authored
Tunnels in shared process should be per remote (microsoft#135937)
Fixes microsoft/vscode-remote-release#5706
1 parent aaa4e0a commit ec64531

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed

src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ import { IExtensionHostStarter, ipcExtensionHostStarterChannelName } from 'vs/pl
8888
import { ExtensionHostStarter } from 'vs/platform/extensions/node/extensionHostStarter';
8989
import { ISignService } from 'vs/platform/sign/common/sign';
9090
import { SignService } from 'vs/platform/sign/node/signService';
91-
import { ITunnelService } from 'vs/platform/remote/common/tunnel';
92-
import { TunnelService } from 'vs/platform/remote/node/tunnelService';
91+
import { ISharedTunnelsService } from 'vs/platform/remote/common/tunnel';
92+
import { SharedTunnelsService } from 'vs/platform/remote/node/tunnelService';
9393
import { ipcSharedProcessTunnelChannelName, ISharedProcessTunnelService } from 'vs/platform/remote/common/sharedProcessTunnelService';
9494
import { SharedProcessTunnelService } from 'vs/platform/remote/node/sharedProcessTunnelService';
9595
import { ipcSharedProcessWorkerChannelName, ISharedProcessWorkerConfiguration, ISharedProcessWorkerService } from 'vs/platform/sharedProcess/common/sharedProcessWorkerService';
@@ -326,7 +326,7 @@ class SharedProcessMain extends Disposable {
326326
services.set(ISignService, new SyncDescriptor(SignService));
327327

328328
// Tunnel
329-
services.set(ITunnelService, new SyncDescriptor(TunnelService));
329+
services.set(ISharedTunnelsService, new SyncDescriptor(SharedTunnelsService));
330330
services.set(ISharedProcessTunnelService, new SyncDescriptor(SharedProcessTunnelService));
331331

332332
return new InstantiationService(services);

src/vs/platform/remote/common/sharedProcessTunnelService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface ISharedProcessTunnelService {
2929
* Start a previously created tunnel.
3030
* Can only be called once per created tunnel.
3131
*/
32-
startTunnel(id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel>;
32+
startTunnel(authority: string, id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel>;
3333
/**
3434
* Set the remote address info for a previously created tunnel.
3535
* Should be called as often as the resolver resolves.

src/vs/platform/remote/common/tunnel.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ILogService } from 'vs/platform/log/common/log';
1313
import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection';
1414

1515
export const ITunnelService = createDecorator<ITunnelService>('tunnelService');
16+
export const ISharedTunnelsService = createDecorator<ISharedTunnelsService>('sharedTunnelsService');
1617

1718
export interface RemoteTunnel {
1819
readonly tunnelRemotePort: number;
@@ -110,6 +111,12 @@ export interface ITunnel {
110111
dispose(): Promise<void> | void;
111112
}
112113

114+
export interface ISharedTunnelsService {
115+
readonly _serviceBrand: undefined;
116+
117+
openTunnel(authority: string, addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> | undefined;
118+
}
119+
113120
export interface ITunnelService {
114121
readonly _serviceBrand: undefined;
115122

src/vs/platform/remote/node/sharedProcessTunnelService.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { ILogService } from 'vs/platform/log/common/log';
77
import { ISharedProcessTunnel, ISharedProcessTunnelService } from 'vs/platform/remote/common/sharedProcessTunnelService';
8-
import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
8+
import { ISharedTunnelsService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
99
import { IAddress, IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection';
1010
import { Disposable } from 'vs/base/common/lifecycle';
1111
import { canceled } from 'vs/base/common/errors';
@@ -55,7 +55,7 @@ export class SharedProcessTunnelService extends Disposable implements ISharedPro
5555
private readonly _disposedTunnels: Set<string> = new Set<string>();
5656

5757
constructor(
58-
@ITunnelService private readonly _tunnelService: ITunnelService,
58+
@ISharedTunnelsService private readonly _tunnelService: ISharedTunnelsService,
5959
@ILogService private readonly _logService: ILogService,
6060
) {
6161
super();
@@ -71,10 +71,10 @@ export class SharedProcessTunnelService extends Disposable implements ISharedPro
7171
return { id };
7272
}
7373

74-
async startTunnel(id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel> {
74+
async startTunnel(authority: string, id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel> {
7575
const tunnelData = new TunnelData();
7676

77-
const tunnel = await Promise.resolve(this._tunnelService.openTunnel(tunnelData, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded));
77+
const tunnel = await Promise.resolve(this._tunnelService.openTunnel(authority, tunnelData, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded));
7878
if (!tunnel) {
7979
this._logService.info(`[SharedProcessTunnelService] Could not create a tunnel to ${tunnelRemoteHost}:${tunnelRemotePort} (remote).`);
8080
tunnelData.dispose();

src/vs/platform/remote/node/tunnelService.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
1414
import { ILogService } from 'vs/platform/log/common/log';
1515
import { IProductService } from 'vs/platform/product/common/productService';
1616
import { connectRemoteAgentTunnel, IAddressProvider, IConnectionOptions, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
17-
import { AbstractTunnelService, isAllInterfaces, isLocalhost, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/remote/common/tunnel';
17+
import { AbstractTunnelService, isAllInterfaces, ISharedTunnelsService as ISharedTunnelsService, isLocalhost, ITunnelService, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/remote/common/tunnel';
1818
import { ISignService } from 'vs/platform/sign/common/sign';
1919

2020
async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise<RemoteTunnel> {
@@ -189,3 +189,33 @@ export class TunnelService extends BaseTunnelService {
189189
super(nodeSocketFactory, logService, signService, productService, configurationService);
190190
}
191191
}
192+
193+
export class SharedTunnelsService extends Disposable implements ISharedTunnelsService {
194+
declare readonly _serviceBrand: undefined;
195+
private readonly _tunnelServices: Map<string, ITunnelService> = new Map();
196+
197+
public constructor(
198+
@ILogService protected readonly logService: ILogService,
199+
@IProductService private readonly productService: IProductService,
200+
@ISignService private readonly signService: ISignService,
201+
@IConfigurationService private readonly configurationService: IConfigurationService,
202+
) {
203+
super();
204+
}
205+
206+
async openTunnel(authority: string, addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> {
207+
this.logService.trace(`ForwardedPorts: (SharedTunnelService) openTunnel request for ${remoteHost}:${remotePort} on local port ${localPort}.`);
208+
if (!this._tunnelServices.has(authority)) {
209+
const tunnelService = new TunnelService(this.logService, this.signService, this.productService, this.configurationService);
210+
this._register(tunnelService);
211+
this._tunnelServices.set(authority, tunnelService);
212+
tunnelService.onTunnelClosed(async () => {
213+
if ((await tunnelService.tunnels).length === 0) {
214+
tunnelService.dispose();
215+
this._tunnelServices.delete(authority);
216+
}
217+
});
218+
}
219+
return this._tunnelServices.get(authority)!.openTunnel(addressProvider, remoteHost, remotePort, localPort, elevateIfNeeded, privacy, protocol);
220+
}
221+
}

src/vs/workbench/services/remote/electron-sandbox/tunnelServiceImpl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ export class TunnelService extends AbstractTunnelService {
9292
private async _createSharedProcessTunnel(addressProvider: IAddressProvider, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<RemoteTunnel> {
9393
const { id } = await this._sharedProcessTunnelService.createTunnel();
9494
this._activeSharedProcessTunnels.add(id);
95-
96-
const result = await this._sharedProcessTunnelService.startTunnel(id, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded);
95+
const authority = this._environmentService.remoteAuthority!;
96+
const result = await this._sharedProcessTunnelService.startTunnel(authority, id, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded);
9797
const tunnel = this._instantiationService.createInstance(SharedProcessTunnel, id, addressProvider, tunnelRemoteHost, tunnelRemotePort, result.tunnelLocalPort, result.localAddress, () => {
9898
this._activeSharedProcessTunnels.delete(id);
9999
});

0 commit comments

Comments
 (0)