diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 7ce33fccd67c3..d945cf074c9ca 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -425,6 +425,7 @@ export class TunnelModel extends Disposable { public readonly configPortsAttributes: PortsAttributes; private restoreListener: IDisposable | undefined; private knownPortsRestoreValue: string | undefined; + private unrestoredExtensionTunnels: Map = new Map(); private portAttributesProviders: PortAttributesProvider[] = []; @@ -551,7 +552,9 @@ export class TunnelModel extends Disposable { const tunnels = JSON.parse(tunnelRestoreValue) ?? []; this.logService.trace(`ForwardedPorts: (TunnelModel) restoring ports ${tunnels.map(tunnel => tunnel.remotePort).join(', ')}`); for (const tunnel of tunnels) { - if (!mapHasAddressLocalhostOrAllInterfaces(this.detected, tunnel.remoteHost, tunnel.remotePort)) { + const alreadyForwarded = mapHasAddressLocalhostOrAllInterfaces(this.detected, tunnel.remoteHost, tunnel.remotePort); + // Extension forwarded ports should only be updated, not restored. + if ((tunnel.source.source === TunnelSource.User && !alreadyForwarded) || (tunnel.source.source === TunnelSource.Extension && alreadyForwarded)) { await this.forward({ remote: { host: tunnel.remoteHost, port: tunnel.remotePort }, local: tunnel.localPort, @@ -559,6 +562,8 @@ export class TunnelModel extends Disposable { privacy: tunnel.privacy, elevateIfNeeded: true }); + } else if (tunnel.source.source === TunnelSource.Extension && !alreadyForwarded) { + this.unrestoredExtensionTunnels.set(makeAddress(tunnel.remoteHost, tunnel.remotePort), tunnel); } } } @@ -580,7 +585,7 @@ export class TunnelModel extends Disposable { @debounce(1000) private async storeForwarded() { if (this.configurationService.getValue('remote.restoreForwardedPorts')) { - const valueToStore = JSON.stringify(Array.from(this.forwarded.values()).filter(value => value.source.source === TunnelSource.User)); + const valueToStore = JSON.stringify(Array.from(this.forwarded.values()).filter(value => value.source.source !== TunnelSource.Auto)); if (valueToStore !== this.knownPortsRestoreValue) { this.knownPortsRestoreValue = valueToStore; const key = await this.getStorageKey(); @@ -626,7 +631,7 @@ export class TunnelModel extends Disposable { const key = makeAddress(tunnelProperties.remote.host, tunnelProperties.remote.port); this.inProgress.set(key, true); - const tunnel = await this.tunnelService.openTunnel(addressProvider, tunnelProperties.remote.host, tunnelProperties.remote.port, undefined, localPort, (!tunnelProperties.elevateIfNeeded) ? attributes?.elevateIfNeeded : tunnelProperties.elevateIfNeeded, tunnelProperties.privacy, attributes?.protocol); + let tunnel = await this.tunnelService.openTunnel(addressProvider, tunnelProperties.remote.host, tunnelProperties.remote.port, undefined, localPort, (!tunnelProperties.elevateIfNeeded) ? attributes?.elevateIfNeeded : tunnelProperties.elevateIfNeeded, tunnelProperties.privacy, attributes?.protocol); if (tunnel && tunnel.localAddress) { const matchingCandidate = mapHasAddressLocalhostOrAllInterfaces(this._candidates ?? new Map(), tunnelProperties.remote.host, tunnelProperties.remote.port); const protocol = (tunnel.protocol ? @@ -653,6 +658,19 @@ export class TunnelModel extends Disposable { await this.storeForwarded(); await this.showPortMismatchModalIfNeeded(tunnel, localPort, attributes); this._onForwardPort.fire(newForward); + if (this.unrestoredExtensionTunnels.has(key)) { + const updateProps = this.unrestoredExtensionTunnels.get(key); + this.unrestoredExtensionTunnels.delete(key); + if (updateProps) { + tunnel = await this.forward({ + remote: { host: newForward.remoteHost, port: newForward.remotePort }, + local: newForward.localPort, + name: newForward.name, + privacy: updateProps.privacy, + elevateIfNeeded: true, + }); + } + } return tunnel; } this.inProgress.delete(key);