Tunnels in shared process should be per remote (#135937)
Fixes microsoft/vscode-remote-release#5706
This commit is contained in:
parent
aaa4e0a341
commit
ec64531d1f
|
@ -88,8 +88,8 @@ import { IExtensionHostStarter, ipcExtensionHostStarterChannelName } from 'vs/pl
|
|||
import { ExtensionHostStarter } from 'vs/platform/extensions/node/extensionHostStarter';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { SignService } from 'vs/platform/sign/node/signService';
|
||||
import { ITunnelService } from 'vs/platform/remote/common/tunnel';
|
||||
import { TunnelService } from 'vs/platform/remote/node/tunnelService';
|
||||
import { ISharedTunnelsService } from 'vs/platform/remote/common/tunnel';
|
||||
import { SharedTunnelsService } from 'vs/platform/remote/node/tunnelService';
|
||||
import { ipcSharedProcessTunnelChannelName, ISharedProcessTunnelService } from 'vs/platform/remote/common/sharedProcessTunnelService';
|
||||
import { SharedProcessTunnelService } from 'vs/platform/remote/node/sharedProcessTunnelService';
|
||||
import { ipcSharedProcessWorkerChannelName, ISharedProcessWorkerConfiguration, ISharedProcessWorkerService } from 'vs/platform/sharedProcess/common/sharedProcessWorkerService';
|
||||
|
@ -326,7 +326,7 @@ class SharedProcessMain extends Disposable {
|
|||
services.set(ISignService, new SyncDescriptor(SignService));
|
||||
|
||||
// Tunnel
|
||||
services.set(ITunnelService, new SyncDescriptor(TunnelService));
|
||||
services.set(ISharedTunnelsService, new SyncDescriptor(SharedTunnelsService));
|
||||
services.set(ISharedProcessTunnelService, new SyncDescriptor(SharedProcessTunnelService));
|
||||
|
||||
return new InstantiationService(services);
|
||||
|
|
|
@ -29,7 +29,7 @@ export interface ISharedProcessTunnelService {
|
|||
* Start a previously created tunnel.
|
||||
* Can only be called once per created tunnel.
|
||||
*/
|
||||
startTunnel(id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel>;
|
||||
startTunnel(authority: string, id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel>;
|
||||
/**
|
||||
* Set the remote address info for a previously created tunnel.
|
||||
* Should be called as often as the resolver resolves.
|
||||
|
|
|
@ -13,6 +13,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
|||
import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
|
||||
export const ITunnelService = createDecorator<ITunnelService>('tunnelService');
|
||||
export const ISharedTunnelsService = createDecorator<ISharedTunnelsService>('sharedTunnelsService');
|
||||
|
||||
export interface RemoteTunnel {
|
||||
readonly tunnelRemotePort: number;
|
||||
|
@ -110,6 +111,12 @@ export interface ITunnel {
|
|||
dispose(): Promise<void> | void;
|
||||
}
|
||||
|
||||
export interface ISharedTunnelsService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
openTunnel(authority: string, addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> | undefined;
|
||||
}
|
||||
|
||||
export interface ITunnelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ISharedProcessTunnel, ISharedProcessTunnelService } from 'vs/platform/remote/common/sharedProcessTunnelService';
|
||||
import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { ISharedTunnelsService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { IAddress, IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
|
@ -55,7 +55,7 @@ export class SharedProcessTunnelService extends Disposable implements ISharedPro
|
|||
private readonly _disposedTunnels: Set<string> = new Set<string>();
|
||||
|
||||
constructor(
|
||||
@ITunnelService private readonly _tunnelService: ITunnelService,
|
||||
@ISharedTunnelsService private readonly _tunnelService: ISharedTunnelsService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
|
@ -71,10 +71,10 @@ export class SharedProcessTunnelService extends Disposable implements ISharedPro
|
|||
return { id };
|
||||
}
|
||||
|
||||
async startTunnel(id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel> {
|
||||
async startTunnel(authority: string, id: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<ISharedProcessTunnel> {
|
||||
const tunnelData = new TunnelData();
|
||||
|
||||
const tunnel = await Promise.resolve(this._tunnelService.openTunnel(tunnelData, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded));
|
||||
const tunnel = await Promise.resolve(this._tunnelService.openTunnel(authority, tunnelData, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded));
|
||||
if (!tunnel) {
|
||||
this._logService.info(`[SharedProcessTunnelService] Could not create a tunnel to ${tunnelRemoteHost}:${tunnelRemotePort} (remote).`);
|
||||
tunnelData.dispose();
|
||||
|
|
|
@ -14,7 +14,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { connectRemoteAgentTunnel, IAddressProvider, IConnectionOptions, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { AbstractTunnelService, isAllInterfaces, isLocalhost, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/remote/common/tunnel';
|
||||
import { AbstractTunnelService, isAllInterfaces, ISharedTunnelsService as ISharedTunnelsService, isLocalhost, ITunnelService, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/remote/common/tunnel';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
|
||||
async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise<RemoteTunnel> {
|
||||
|
@ -189,3 +189,33 @@ export class TunnelService extends BaseTunnelService {
|
|||
super(nodeSocketFactory, logService, signService, productService, configurationService);
|
||||
}
|
||||
}
|
||||
|
||||
export class SharedTunnelsService extends Disposable implements ISharedTunnelsService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
private readonly _tunnelServices: Map<string, ITunnelService> = new Map();
|
||||
|
||||
public constructor(
|
||||
@ILogService protected readonly logService: ILogService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@ISignService private readonly signService: ISignService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async openTunnel(authority: string, addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> {
|
||||
this.logService.trace(`ForwardedPorts: (SharedTunnelService) openTunnel request for ${remoteHost}:${remotePort} on local port ${localPort}.`);
|
||||
if (!this._tunnelServices.has(authority)) {
|
||||
const tunnelService = new TunnelService(this.logService, this.signService, this.productService, this.configurationService);
|
||||
this._register(tunnelService);
|
||||
this._tunnelServices.set(authority, tunnelService);
|
||||
tunnelService.onTunnelClosed(async () => {
|
||||
if ((await tunnelService.tunnels).length === 0) {
|
||||
tunnelService.dispose();
|
||||
this._tunnelServices.delete(authority);
|
||||
}
|
||||
});
|
||||
}
|
||||
return this._tunnelServices.get(authority)!.openTunnel(addressProvider, remoteHost, remotePort, localPort, elevateIfNeeded, privacy, protocol);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,8 +92,8 @@ export class TunnelService extends AbstractTunnelService {
|
|||
private async _createSharedProcessTunnel(addressProvider: IAddressProvider, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort: number | undefined, elevateIfNeeded: boolean | undefined): Promise<RemoteTunnel> {
|
||||
const { id } = await this._sharedProcessTunnelService.createTunnel();
|
||||
this._activeSharedProcessTunnels.add(id);
|
||||
|
||||
const result = await this._sharedProcessTunnelService.startTunnel(id, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded);
|
||||
const authority = this._environmentService.remoteAuthority!;
|
||||
const result = await this._sharedProcessTunnelService.startTunnel(authority, id, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort, elevateIfNeeded);
|
||||
const tunnel = this._instantiationService.createInstance(SharedProcessTunnel, id, addressProvider, tunnelRemoteHost, tunnelRemotePort, result.tunnelLocalPort, result.localAddress, () => {
|
||||
this._activeSharedProcessTunnels.delete(id);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue