1
>
/*---------------------------------------------------------------------------------------------
tunnel.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { CancellationToken } from '../../../base/common/cancellation.js';
7
>
import { Emitter, Event } from '../../../base/common/event.js';
8
>
import { IDisposable, Disposable } from '../../../base/common/lifecycle.js';
9
>
import { OperatingSystem } from '../../../base/common/platform.js';
10
>
import { URI } from '../../../base/common/uri.js';
11
>
import { IConfigurationService } from '../../configuration/common/configuration.js';
12
>
import { createDecorator } from '../../instantiation/common/instantiation.js';
13
>
import { ILogService } from '../../log/common/log.js';
14
>
import { IAddressProvider } from '../../remote/common/remoteAgentConnection.js';
15
>
import { TunnelPrivacy } from '../../remote/common/remoteAuthorityResolver.js';
16
>
17
>
export const ITunnelService = createDecorator<ITunnelService>('tunnelService');
18
>
export const ISharedTunnelsService = createDecorator<ISharedTunnelsService>('sharedTunnelsService');
19
>
20
>
export interface RemoteTunnel {
21
>
readonly tunnelRemotePort: number;
22
>
readonly tunnelRemoteHost: string;
23
>
readonly tunnelLocalPort?: number;
24
>
readonly localAddress: string;
25
>
readonly privacy: string;
26
>
readonly protocol?: string;
27
>
dispose(silent?: boolean): Promise<void>;
28
>
}
29
>
30
>
export function isRemoteTunnel(something: unknown): something is RemoteTunnel {
31
const asTunnel: Partial<RemoteTunnel> = something as Partial<RemoteTunnel>;
32
return !!(asTunnel.tunnelRemotePort && asTunnel.tunnelRemoteHost && asTunnel.localAddress && asTunnel.privacy && asTunnel.dispose);
33
}
35
>
export interface TunnelOptions {
36
>
remoteAddress: { port: number; host: string };
37
>
localAddressPort?: number;
38
>
label?: string;
39
>
public?: boolean;
40
>
privacy?: string;
41
>
protocol?: string;
42
>
}
43
>
44
>
export enum TunnelProtocol {
45
>
Http = 'http',
46
>
Https = 'https'
47
>
}
48
>
49
>
export enum TunnelPrivacyId {
50
>
ConstantPrivate = 'constantPrivate', // private, and changing is unsupported
51
>
Private = 'private',
52
>
Public = 'public'
53
>
}
54
>
55
>
export interface TunnelCreationOptions {
56
>
elevationRequired?: boolean;
57
>
}
58
>
59
>
export interface TunnelProviderFeatures {
60
>
elevation: boolean;
61
>
/**
62
>
* @deprecated
63
>
*/
64
>
public?: boolean;
65
>
privacyOptions: TunnelPrivacy[];
66
>
protocol: boolean;
67
>
}
68
>
69
>
export interface ITunnelProvider {
70
>
forwardPort(tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise<RemoteTunnel | string | undefined> | undefined;
71
>
}
72
>
73
>
export function isTunnelProvider(addressOrTunnelProvider: IAddressProvider | ITunnelProvider): addressOrTunnelProvider is ITunnelProvider {
74
return !!(addressOrTunnelProvider as ITunnelProvider).forwardPort;
75
}
77
>
export enum ProvidedOnAutoForward {
78
>
Notify = 1,
79
>
OpenBrowser = 2,
80
>
OpenPreview = 3,
81
>
Silent = 4,
82
>
Ignore = 5,
83
>
OpenBrowserOnce = 6
84
>
}
85
>
86
>
export interface ProvidedPortAttributes {
87
>
port: number;
88
>
autoForwardAction: ProvidedOnAutoForward;
89
>
}
90
>
91
>
export interface PortAttributesProvider {
92
>
providePortAttributes(ports: number[], pid: number | undefined, commandLine: string | undefined, token: CancellationToken): Promise<ProvidedPortAttributes[]>;
93
>
}
94
>
95
>
export interface ITunnel {
96
>
remoteAddress: { port: number; host: string };
97
>
98
>
/**
99
>
* The complete local address(ex. localhost:1234)
100
>
*/
101
>
localAddress: string;
102
>
103
>
/**
104
>
* @deprecated Use privacy instead
105
>
*/
106
>
public?: boolean;
107
>
108
>
privacy?: string;
109
>
110
>
protocol?: string;
111
>
112
>
/**
113
>
* Implementers of Tunnel should fire onDidDispose when dispose is called.
114
>
*/
115
>
readonly onDidDispose: Event<void>;
116
>
117
>
dispose(): Promise<void> | void;
118
>
}
119
>
120
>
export interface ISharedTunnelsService {
121
>
readonly _serviceBrand: undefined;
122
>
123
>
openTunnel(authority: string, addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localHost: string, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | string | undefined> | undefined;
124
>
}
125
>
126
>
export interface ITunnelService {
127
>
readonly _serviceBrand: undefined;
128
>
129
>
readonly tunnels: Promise<readonly RemoteTunnel[]>;
130
>
readonly canChangePrivacy: boolean;
131
>
readonly privacyOptions: TunnelPrivacy[];
132
>
readonly onTunnelOpened: Event<RemoteTunnel>;
133
>
readonly onTunnelClosed: Event<{ host: string; port: number }>;
134
>
readonly canElevate: boolean;
135
>
readonly canChangeProtocol: boolean;
136
>
readonly hasTunnelProvider: boolean;
137
>
readonly onAddedTunnelProvider: Event<void>;
138
>
139
>
canTunnel(uri: URI): boolean;
140
>
openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localHost?: string, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | string | undefined> | undefined;
141
>
getExistingTunnel(remoteHost: string, remotePort: number): Promise<RemoteTunnel | string | undefined>;
142
>
setEnvironmentTunnel(remoteHost: string, remotePort: number, localAddress: string, privacy: string, protocol: string): void;
143
>
closeTunnel(remoteHost: string, remotePort: number): Promise<void>;
144
>
setTunnelProvider(provider: ITunnelProvider | undefined): IDisposable;
145
>
setTunnelFeatures(features: TunnelProviderFeatures): void;
146
>
isPortPrivileged(port: number): boolean;
147
>
}
148
>
149
>
export function extractLocalHostUriMetaDataForPortMapping(uri: URI): { address: string; port: number } | undefined {
150
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
151
return undefined;