Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
8e2b3047
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8e2b3047
编写于
12月 18, 2019
作者:
A
Alex Ross
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Enable more than just localhost for port forwarding providers
Part of #81388
上级
c7ab68cc
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
187 addition
and
133 deletion
+187
-133
src/vs/platform/remote/common/tunnel.ts
src/vs/platform/remote/common/tunnel.ts
+3
-3
src/vs/platform/remote/common/tunnelService.ts
src/vs/platform/remote/common/tunnelService.ts
+4
-4
src/vs/workbench/api/browser/mainThreadTunnelService.ts
src/vs/workbench/api/browser/mainThreadTunnelService.ts
+3
-3
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+2
-2
src/vs/workbench/api/common/extHostTunnelService.ts
src/vs/workbench/api/common/extHostTunnelService.ts
+1
-1
src/vs/workbench/api/node/extHostTunnelService.ts
src/vs/workbench/api/node/extHostTunnelService.ts
+5
-5
src/vs/workbench/contrib/remote/browser/tunnelView.ts
src/vs/workbench/contrib/remote/browser/tunnelView.ts
+40
-28
src/vs/workbench/contrib/webview/common/portMapping.ts
src/vs/workbench/contrib/webview/common/portMapping.ts
+1
-1
src/vs/workbench/electron-browser/window.ts
src/vs/workbench/electron-browser/window.ts
+1
-1
src/vs/workbench/services/remote/common/remoteExplorerService.ts
...workbench/services/remote/common/remoteExplorerService.ts
+78
-60
src/vs/workbench/services/remote/node/tunnelService.ts
src/vs/workbench/services/remote/node/tunnelService.ts
+49
-25
未找到文件。
src/vs/platform/remote/common/tunnel.ts
浏览文件 @
8e2b3047
...
...
@@ -33,10 +33,10 @@ export interface ITunnelService {
readonly
tunnels
:
Promise
<
readonly
RemoteTunnel
[]
>
;
readonly
onTunnelOpened
:
Event
<
RemoteTunnel
>
;
readonly
onTunnelClosed
:
Event
<
number
>
;
readonly
onTunnelClosed
:
Event
<
{
host
:
string
,
port
:
number
}
>
;
openTunnel
(
remotePort
:
number
,
localPort
?:
number
):
Promise
<
RemoteTunnel
>
|
undefined
;
closeTunnel
(
remotePort
:
number
):
Promise
<
void
>
;
openTunnel
(
remote
Host
:
string
|
undefined
,
remote
Port
:
number
,
localPort
?:
number
):
Promise
<
RemoteTunnel
>
|
undefined
;
closeTunnel
(
remote
Host
:
string
,
remote
Port
:
number
):
Promise
<
void
>
;
setTunnelProvider
(
provider
:
ITunnelProvider
|
undefined
):
IDisposable
;
}
...
...
src/vs/platform/remote/common/tunnelService.ts
浏览文件 @
8e2b3047
...
...
@@ -13,12 +13,12 @@ export class NoOpTunnelService implements ITunnelService {
public
readonly
tunnels
:
Promise
<
readonly
RemoteTunnel
[]
>
=
Promise
.
resolve
([]);
private
_onTunnelOpened
:
Emitter
<
RemoteTunnel
>
=
new
Emitter
();
public
onTunnelOpened
:
Event
<
RemoteTunnel
>
=
this
.
_onTunnelOpened
.
event
;
private
_onTunnelClosed
:
Emitter
<
number
>
=
new
Emitter
();
public
onTunnelClosed
:
Event
<
number
>
=
this
.
_onTunnelClosed
.
event
;
openTunnel
(
_remotePort
:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
private
_onTunnelClosed
:
Emitter
<
{
host
:
string
,
port
:
number
}
>
=
new
Emitter
();
public
onTunnelClosed
:
Event
<
{
host
:
string
,
port
:
number
}
>
=
this
.
_onTunnelClosed
.
event
;
openTunnel
(
_remote
Host
:
string
,
_remote
Port
:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
return
undefined
;
}
async
closeTunnel
(
_remotePort
:
number
):
Promise
<
void
>
{
async
closeTunnel
(
_remote
Host
:
string
,
_remote
Port
:
number
):
Promise
<
void
>
{
}
setTunnelProvider
(
provider
:
ITunnelProvider
|
undefined
):
IDisposable
{
throw
new
Error
(
'
Method not implemented.
'
);
...
...
src/vs/workbench/api/browser/mainThreadTunnelService.ts
浏览文件 @
8e2b3047
...
...
@@ -22,15 +22,15 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
}
async
$openTunnel
(
tunnelOptions
:
TunnelOptions
):
Promise
<
TunnelDto
|
undefined
>
{
const
tunnel
=
await
this
.
remoteExplorerService
.
forward
(
tunnelOptions
.
remote
.
port
,
tunnelOptions
.
localPort
,
tunnelOptions
.
name
);
const
tunnel
=
await
this
.
remoteExplorerService
.
forward
(
tunnelOptions
.
remote
,
tunnelOptions
.
localPort
,
tunnelOptions
.
name
);
if
(
tunnel
)
{
return
TunnelDto
.
fromServiceTunnel
(
tunnel
);
}
return
undefined
;
}
async
$closeTunnel
(
remote
Port
:
number
):
Promise
<
void
>
{
return
this
.
remoteExplorerService
.
close
(
remote
Port
);
async
$closeTunnel
(
remote
:
{
host
:
string
,
port
:
number
}
):
Promise
<
void
>
{
return
this
.
remoteExplorerService
.
close
(
remote
);
}
async
$registerCandidateFinder
():
Promise
<
void
>
{
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
8e2b3047
...
...
@@ -774,7 +774,7 @@ export interface MainThreadWindowShape extends IDisposable {
export
interface
MainThreadTunnelServiceShape
extends
IDisposable
{
$openTunnel
(
tunnelOptions
:
TunnelOptions
):
Promise
<
TunnelDto
|
undefined
>
;
$closeTunnel
(
remote
Port
:
number
):
Promise
<
void
>
;
$closeTunnel
(
remote
:
{
host
:
string
,
port
:
number
}
):
Promise
<
void
>
;
$registerCandidateFinder
():
Promise
<
void
>
;
$setTunnelProvider
():
Promise
<
void
>
;
}
...
...
@@ -1395,7 +1395,7 @@ export interface ExtHostStorageShape {
export
interface
ExtHostTunnelServiceShape
{
$findCandidatePorts
():
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
;
$findCandidatePorts
():
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
;
$forwardPort
(
tunnelOptions
:
TunnelOptions
):
Promise
<
TunnelDto
>
|
undefined
;
$closeTunnel
(
remote
:
{
host
:
string
,
port
:
number
}):
Promise
<
void
>
;
}
...
...
src/vs/workbench/api/common/extHostTunnelService.ts
浏览文件 @
8e2b3047
...
...
@@ -48,7 +48,7 @@ export class ExtHostTunnelService implements IExtHostTunnelService {
async
makeTunnel
(
forward
:
TunnelOptions
):
Promise
<
vscode
.
Tunnel
|
undefined
>
{
return
undefined
;
}
async
$findCandidatePorts
():
Promise
<
{
port
:
number
;
detail
:
string
;
}[]
>
{
async
$findCandidatePorts
():
Promise
<
{
host
:
string
,
port
:
number
;
detail
:
string
;
}[]
>
{
return
[];
}
async
setForwardPortProvider
(
provider
:
vscode
.
RemoteAuthorityResolver
|
undefined
):
Promise
<
IDisposable
>
{
return
{
dispose
:
()
=>
{
}
};
}
...
...
src/vs/workbench/api/node/extHostTunnelService.ts
浏览文件 @
8e2b3047
...
...
@@ -52,7 +52,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
const
tunnel
=
await
this
.
_proxy
.
$openTunnel
(
forward
);
if
(
tunnel
)
{
const
disposableTunnel
:
vscode
.
Tunnel
=
new
ExtensionTunnel
(
tunnel
.
remote
,
tunnel
.
localAddress
,
()
=>
{
return
this
.
_proxy
.
$closeTunnel
(
tunnel
.
remote
.
port
);
return
this
.
_proxy
.
$closeTunnel
(
tunnel
.
remote
);
});
this
.
_register
(
disposableTunnel
);
return
disposableTunnel
;
...
...
@@ -95,7 +95,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
this
.
_extensionTunnels
.
set
(
tunnelOptions
.
remote
.
host
,
new
Map
());
}
this
.
_extensionTunnels
.
get
(
tunnelOptions
.
remote
.
host
)
!
.
set
(
tunnelOptions
.
remote
.
port
,
tunnel
);
this
.
_register
(
tunnel
.
onDispose
(()
=>
this
.
_proxy
.
$closeTunnel
(
tunnel
.
remote
.
port
)));
this
.
_register
(
tunnel
.
onDispose
(()
=>
this
.
_proxy
.
$closeTunnel
(
tunnel
.
remote
)));
return
Promise
.
resolve
(
TunnelDto
.
fromApiTunnel
(
tunnel
));
});
}
...
...
@@ -104,12 +104,12 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
}
async
$findCandidatePorts
():
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
{
async
$findCandidatePorts
():
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
{
if
(
!
isLinux
)
{
return
[];
}
const
ports
:
{
port
:
number
,
detail
:
string
}[]
=
[];
const
ports
:
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
=
[];
const
tcp
:
string
=
fs
.
readFileSync
(
'
/proc/net/tcp
'
,
'
utf8
'
);
const
tcp6
:
string
=
fs
.
readFileSync
(
'
/proc/net/tcp6
'
,
'
utf8
'
);
const
procSockets
:
string
=
await
(
new
Promise
(
resolve
=>
{
...
...
@@ -150,7 +150,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
connections
.
filter
((
connection
=>
socketMap
[
connection
.
socket
])).
forEach
(({
socket
,
ip
,
port
})
=>
{
const
command
=
processMap
[
socketMap
[
socket
].
pid
].
cmd
;
if
(
!
command
.
match
(
'
.*
\
.vscode
\
-server
\
-[a-zA-Z]+
\
/bin.*
'
)
&&
(
command
.
indexOf
(
'
out/vs/server/main.js
'
)
===
-
1
))
{
ports
.
push
({
port
,
detail
:
processMap
[
socketMap
[
socket
].
pid
].
cmd
});
ports
.
push
({
host
:
ip
,
port
,
detail
:
processMap
[
socketMap
[
socket
].
pid
].
cmd
});
}
});
...
...
src/vs/workbench/contrib/remote/browser/tunnelView.ts
浏览文件 @
8e2b3047
...
...
@@ -26,7 +26,7 @@ import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
import
{
ActionRunner
,
IAction
}
from
'
vs/base/common/actions
'
;
import
{
IMenuService
,
MenuId
,
IMenu
,
MenuRegistry
,
MenuItemAction
}
from
'
vs/platform/actions/common/actions
'
;
import
{
createAndFillInContextMenuActions
,
createAndFillInActionBarActions
,
ContextAwareMenuEntryActionViewItem
}
from
'
vs/platform/actions/browser/menuEntryActionViewItem
'
;
import
{
IRemoteExplorerService
,
TunnelModel
}
from
'
vs/workbench/services/remote/common/remoteExplorerService
'
;
import
{
IRemoteExplorerService
,
TunnelModel
,
MakeAddress
}
from
'
vs/workbench/services/remote/common/remoteExplorerService
'
;
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
import
{
INotificationService
}
from
'
vs/platform/notification/common/notification
'
;
import
{
InputBox
,
MessageType
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
...
...
@@ -105,13 +105,13 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel {
get
forwarded
():
TunnelItem
[]
{
return
Array
.
from
(
this
.
model
.
forwarded
.
values
()).
map
(
tunnel
=>
{
return
new
TunnelItem
(
TunnelType
.
Forwarded
,
tunnel
.
remote
,
tunnel
.
localAddress
,
tunnel
.
closeable
,
tunnel
.
name
,
tunnel
.
description
);
return
new
TunnelItem
(
TunnelType
.
Forwarded
,
tunnel
.
remote
Host
,
tunnel
.
remotePort
,
tunnel
.
localAddress
,
tunnel
.
closeable
,
tunnel
.
name
,
tunnel
.
description
);
});
}
get
detected
():
TunnelItem
[]
{
return
Array
.
from
(
this
.
model
.
detected
.
values
()).
map
(
tunnel
=>
{
return
new
TunnelItem
(
TunnelType
.
Detected
,
tunnel
.
remote
,
tunnel
.
localAddress
,
false
,
tunnel
.
name
,
tunnel
.
description
);
return
new
TunnelItem
(
TunnelType
.
Detected
,
tunnel
.
remote
Host
,
tunnel
.
remotePort
,
tunnel
.
localAddress
,
false
,
tunnel
.
name
,
tunnel
.
description
);
});
}
...
...
@@ -119,8 +119,9 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel {
return
this
.
model
.
candidates
.
then
(
values
=>
{
const
candidates
:
TunnelItem
[]
=
[];
values
.
forEach
(
value
=>
{
if
(
!
this
.
model
.
forwarded
.
has
(
value
.
port
)
&&
!
this
.
model
.
detected
.
has
(
value
.
port
))
{
candidates
.
push
(
new
TunnelItem
(
TunnelType
.
Candidate
,
value
.
port
,
undefined
,
false
,
undefined
,
value
.
detail
));
const
key
=
MakeAddress
(
value
.
host
,
value
.
port
);
if
(
!
this
.
model
.
forwarded
.
has
(
key
)
&&
!
this
.
model
.
detected
.
has
(
key
))
{
candidates
.
push
(
new
TunnelItem
(
TunnelType
.
Candidate
,
value
.
host
,
value
.
port
,
undefined
,
false
,
undefined
,
value
.
detail
));
}
});
return
candidates
;
...
...
@@ -185,7 +186,7 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer<ITunnelGrou
}
private
isTunnelItem
(
item
:
ITunnelGroup
|
ITunnelItem
):
item
is
ITunnelItem
{
return
!!
((
<
ITunnelItem
>
item
).
remote
);
return
!!
((
<
ITunnelItem
>
item
).
remote
Port
);
}
renderElement
(
element
:
ITreeNode
<
ITunnelGroup
|
ITunnelItem
,
ITunnelGroup
|
ITunnelItem
>
,
index
:
number
,
templateData
:
ITunnelTemplateData
):
void
{
...
...
@@ -196,7 +197,7 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer<ITunnelGrou
templateData
.
actionBar
.
clear
();
let
editableData
:
IEditableData
|
undefined
;
if
(
this
.
isTunnelItem
(
node
))
{
editableData
=
this
.
remoteExplorerService
.
getEditableData
(
node
.
remote
);
editableData
=
this
.
remoteExplorerService
.
getEditableData
(
node
.
remote
Host
,
node
.
remotePort
);
if
(
editableData
)
{
templateData
.
iconLabel
.
element
.
style
.
display
=
'
none
'
;
this
.
renderInputBox
(
templateData
.
container
,
editableData
);
...
...
@@ -204,7 +205,7 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer<ITunnelGrou
templateData
.
iconLabel
.
element
.
style
.
display
=
'
flex
'
;
this
.
renderTunnel
(
node
,
templateData
);
}
}
else
if
((
node
.
tunnelType
===
TunnelType
.
Add
)
&&
(
editableData
=
this
.
remoteExplorerService
.
getEditableData
(
undefined
)))
{
}
else
if
((
node
.
tunnelType
===
TunnelType
.
Add
)
&&
(
editableData
=
this
.
remoteExplorerService
.
getEditableData
(
undefined
,
undefined
)))
{
templateData
.
iconLabel
.
element
.
style
.
display
=
'
none
'
;
this
.
renderInputBox
(
templateData
.
container
,
editableData
);
}
else
{
...
...
@@ -338,7 +339,8 @@ interface ITunnelGroup {
interface
ITunnelItem
{
tunnelType
:
TunnelType
;
remote
:
number
;
remoteHost
:
string
;
remotePort
:
number
;
localAddress
?:
string
;
name
?:
string
;
closeable
?:
boolean
;
...
...
@@ -349,7 +351,8 @@ interface ITunnelItem {
class
TunnelItem
implements
ITunnelItem
{
constructor
(
public
tunnelType
:
TunnelType
,
public
remote
:
number
,
public
remoteHost
:
string
,
public
remotePort
:
number
,
public
localAddress
?:
string
,
public
closeable
?:
boolean
,
public
name
?:
string
,
...
...
@@ -359,9 +362,9 @@ class TunnelItem implements ITunnelItem {
if
(
this
.
name
)
{
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortLabel0
'
,
"
{0}
"
,
this
.
name
);
}
else
if
(
this
.
localAddress
)
{
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortLabel2
'
,
"
{0} to {1}
"
,
this
.
remote
,
this
.
localAddress
);
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortLabel2
'
,
"
{0} to {1}
"
,
this
.
remote
Port
,
this
.
localAddress
);
}
else
{
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortLabel3
'
,
"
{0} not forwarded
"
,
this
.
remote
);
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortLabel3
'
,
"
{0} not forwarded
"
,
this
.
remote
Port
);
}
}
...
...
@@ -369,7 +372,7 @@ class TunnelItem implements ITunnelItem {
if
(
this
.
_description
)
{
return
this
.
_description
;
}
else
if
(
this
.
name
)
{
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortDescription0
'
,
"
{0} to {1}
"
,
this
.
remote
,
this
.
localAddress
);
return
nls
.
localize
(
'
remote.tunnelsView.forwardedPortDescription0
'
,
"
{0} to {1}
"
,
this
.
remote
Port
,
this
.
localAddress
);
}
return
undefined
;
}
...
...
@@ -474,7 +477,7 @@ export class TunnelPanel extends ViewPane {
}));
this
.
_register
(
this
.
remoteExplorerService
.
onDidChangeEditable
(
async
e
=>
{
const
isEditing
=
!!
this
.
remoteExplorerService
.
getEditableData
(
e
);
const
isEditing
=
!!
this
.
remoteExplorerService
.
getEditableData
(
e
.
host
,
e
.
port
);
if
(
!
isEditing
)
{
dom
.
removeClass
(
treeContainer
,
'
highlight
'
);
...
...
@@ -575,12 +578,12 @@ namespace LabelTunnelAction {
return
async
(
accessor
,
arg
)
=>
{
if
(
arg
instanceof
TunnelItem
)
{
const
remoteExplorerService
=
accessor
.
get
(
IRemoteExplorerService
);
remoteExplorerService
.
setEditable
(
arg
.
remote
,
{
remoteExplorerService
.
setEditable
(
arg
.
remote
Host
,
arg
.
remotePort
,
{
onFinish
:
(
value
,
success
)
=>
{
if
(
success
)
{
remoteExplorerService
.
tunnelModel
.
name
(
arg
.
remote
,
value
);
remoteExplorerService
.
tunnelModel
.
name
(
arg
.
remote
Host
,
arg
.
remotePort
,
value
);
}
remoteExplorerService
.
setEditable
(
arg
.
remote
,
null
);
remoteExplorerService
.
setEditable
(
arg
.
remote
Host
,
arg
.
remotePort
,
null
);
},
validationMessage
:
()
=>
null
,
placeholder
:
nls
.
localize
(
'
remote.tunnelsView.labelPlaceholder
'
,
"
Port label
"
),
...
...
@@ -596,24 +599,32 @@ namespace ForwardPortAction {
export
const
ID
=
'
remote.tunnel.forward
'
;
export
const
LABEL
=
nls
.
localize
(
'
remote.tunnel.forward
'
,
"
Forward a Port
"
);
function
parseInput
(
value
:
string
):
{
host
:
string
,
port
:
number
}
|
undefined
{
const
matches
=
value
.
match
(
/^
([
0-9
]
+
\.[
0-9
]
+
\.[
0-9
]
+
\.[
0-9
]
+
\:
|localhost:
)?([
0-9
]
+
)
$/
);
if
(
!
matches
)
{
return
undefined
;
}
return
{
host
:
matches
[
1
]?.
substring
(
0
,
matches
[
1
].
length
-
1
)
||
'
localhost
'
,
port
:
Number
(
matches
[
2
])
};
}
export
function
handler
():
ICommandHandler
{
return
async
(
accessor
,
arg
)
=>
{
const
remoteExplorerService
=
accessor
.
get
(
IRemoteExplorerService
);
if
(
arg
instanceof
TunnelItem
)
{
remoteExplorerService
.
tunnelModel
.
forward
(
arg
.
remote
);
remoteExplorerService
.
forward
({
host
:
arg
.
remoteHost
,
port
:
arg
.
remotePort
}
);
}
else
{
const
viewsService
=
accessor
.
get
(
IViewsService
);
await
viewsService
.
openView
(
TunnelPanel
.
ID
,
true
);
remoteExplorerService
.
setEditable
(
undefined
,
{
remoteExplorerService
.
setEditable
(
undefined
,
undefined
,
{
onFinish
:
(
value
,
success
)
=>
{
if
(
success
)
{
remoteExplorerService
.
tunnelModel
.
forward
(
Number
(
value
));
let
parsed
:
{
host
:
string
,
port
:
number
}
|
undefined
;
if
(
success
&&
(
parsed
=
parseInput
(
value
)))
{
remoteExplorerService
.
forward
({
host
:
parsed
.
host
,
port
:
parsed
.
port
});
}
remoteExplorerService
.
setEditable
(
undefined
,
null
);
remoteExplorerService
.
setEditable
(
undefined
,
undefined
,
null
);
},
validationMessage
:
(
value
)
=>
{
const
asNumber
=
Number
(
value
);
if
((
value
===
''
)
||
isNaN
(
asNumber
)
||
(
asNumber
<
0
)
||
(
asNumber
>
65535
))
{
if
(
!
parseInput
(
value
))
{
return
nls
.
localize
(
'
remote.tunnelsView.portNumberValid
'
,
"
Port number is invalid
"
);
}
return
null
;
...
...
@@ -633,7 +644,7 @@ namespace ClosePortAction {
return
async
(
accessor
,
arg
)
=>
{
if
(
arg
instanceof
TunnelItem
)
{
const
remoteExplorerService
=
accessor
.
get
(
IRemoteExplorerService
);
await
remoteExplorerService
.
tunnelModel
.
close
(
arg
.
remote
);
await
remoteExplorerService
.
close
({
host
:
arg
.
remoteHost
,
port
:
arg
.
remotePort
}
);
}
};
}
...
...
@@ -648,9 +659,10 @@ namespace OpenPortInBrowserAction {
if
(
arg
instanceof
TunnelItem
)
{
const
model
=
accessor
.
get
(
IRemoteExplorerService
).
tunnelModel
;
const
openerService
=
accessor
.
get
(
IOpenerService
);
const
tunnel
=
model
.
forwarded
.
has
(
arg
.
remote
)
?
model
.
forwarded
.
get
(
arg
.
remote
)
:
model
.
detected
.
get
(
arg
.
remote
);
const
key
=
MakeAddress
(
arg
.
remoteHost
,
arg
.
remotePort
);
const
tunnel
=
model
.
forwarded
.
get
(
key
)
||
model
.
detected
.
get
(
key
);
let
address
:
string
|
undefined
;
if
(
tunnel
&&
tunnel
.
localAddress
&&
(
address
=
model
.
address
(
tunnel
.
remote
)))
{
if
(
tunnel
&&
tunnel
.
localAddress
&&
(
address
=
model
.
address
(
tunnel
.
remote
Host
,
tunnel
.
remotePort
)))
{
return
openerService
.
open
(
URI
.
parse
(
'
http://
'
+
address
));
}
return
Promise
.
resolve
();
...
...
@@ -668,7 +680,7 @@ namespace CopyAddressAction {
if
(
arg
instanceof
TunnelItem
)
{
const
model
=
accessor
.
get
(
IRemoteExplorerService
).
tunnelModel
;
const
clipboard
=
accessor
.
get
(
IClipboardService
);
const
address
=
model
.
address
(
arg
.
remote
);
const
address
=
model
.
address
(
arg
.
remote
Host
,
arg
.
remotePort
);
if
(
address
)
{
await
clipboard
.
writeText
(
address
.
toString
());
}
...
...
src/vs/workbench/contrib/webview/common/portMapping.ts
浏览文件 @
8e2b3047
...
...
@@ -68,7 +68,7 @@ export class WebviewPortMappingManager extends Disposable {
if
(
existing
)
{
return
existing
;
}
const
tunnel
=
this
.
tunnelService
.
openTunnel
(
remotePort
);
const
tunnel
=
this
.
tunnelService
.
openTunnel
(
undefined
,
remotePort
);
if
(
tunnel
)
{
this
.
_tunnels
.
set
(
remotePort
,
tunnel
);
}
...
...
src/vs/workbench/electron-browser/window.ts
浏览文件 @
8e2b3047
...
...
@@ -453,7 +453,7 @@ export class ElectronWindow extends Disposable {
if
(
options
?.
allowTunneling
)
{
const
portMappingRequest
=
extractLocalHostUriMetaDataForPortMapping
(
uri
);
if
(
portMappingRequest
)
{
const
tunnel
=
await
this
.
tunnelService
.
openTunnel
(
portMappingRequest
.
port
);
const
tunnel
=
await
this
.
tunnelService
.
openTunnel
(
undefined
,
portMappingRequest
.
port
);
if
(
tunnel
)
{
return
{
resolved
:
uri
.
with
({
authority
:
`127.0.0.1:
${
tunnel
.
tunnelLocalPort
}
`
}),
...
...
src/vs/workbench/services/remote/common/remoteExplorerService.ts
浏览文件 @
8e2b3047
...
...
@@ -18,24 +18,32 @@ export const IRemoteExplorerService = createDecorator<IRemoteExplorerService>('r
export
const
REMOTE_EXPLORER_TYPE_KEY
:
string
=
'
remote.explorerType
'
;
export
interface
Tunnel
{
remote
:
number
;
remoteHost
:
string
;
remotePort
:
number
;
localAddress
:
string
;
local
?:
number
;
local
Port
?:
number
;
name
?:
string
;
description
?:
string
;
closeable
?:
boolean
;
}
export
function
MakeAddress
(
host
:
string
,
port
:
number
):
string
{
if
(
host
=
'
127.0.0.1
'
)
{
host
=
'
localhost
'
;
}
return
host
+
'
:
'
+
port
;
}
export
class
TunnelModel
extends
Disposable
{
readonly
forwarded
:
Map
<
number
,
Tunnel
>
;
readonly
detected
:
Map
<
number
,
Tunnel
>
;
readonly
forwarded
:
Map
<
string
,
Tunnel
>
;
readonly
detected
:
Map
<
string
,
Tunnel
>
;
private
_onForwardPort
:
Emitter
<
Tunnel
>
=
new
Emitter
();
public
onForwardPort
:
Event
<
Tunnel
>
=
this
.
_onForwardPort
.
event
;
private
_onClosePort
:
Emitter
<
number
>
=
new
Emitter
();
public
onClosePort
:
Event
<
number
>
=
this
.
_onClosePort
.
event
;
private
_onPortName
:
Emitter
<
number
>
=
new
Emitter
();
public
onPortName
:
Event
<
number
>
=
this
.
_onPortName
.
event
;
private
_candidateFinder
:
(()
=>
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
)
|
undefined
;
private
_onClosePort
:
Emitter
<
{
host
:
string
,
port
:
number
}
>
=
new
Emitter
();
public
onClosePort
:
Event
<
{
host
:
string
,
port
:
number
}
>
=
this
.
_onClosePort
.
event
;
private
_onPortName
:
Emitter
<
{
host
:
string
,
port
:
number
}
>
=
new
Emitter
();
public
onPortName
:
Event
<
{
host
:
string
,
port
:
number
}
>
=
this
.
_onPortName
.
event
;
private
_candidateFinder
:
(()
=>
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
)
|
undefined
;
constructor
(
@
ITunnelService
private
readonly
tunnelService
:
ITunnelService
...
...
@@ -45,10 +53,11 @@ export class TunnelModel extends Disposable {
this
.
tunnelService
.
tunnels
.
then
(
tunnels
=>
{
tunnels
.
forEach
(
tunnel
=>
{
if
(
tunnel
.
localAddress
)
{
this
.
forwarded
.
set
(
tunnel
.
tunnelRemotePort
,
{
remote
:
tunnel
.
tunnelRemotePort
,
this
.
forwarded
.
set
(
MakeAddress
(
tunnel
.
tunnelRemoteHost
,
tunnel
.
tunnelRemotePort
),
{
remotePort
:
tunnel
.
tunnelRemotePort
,
remoteHost
:
tunnel
.
tunnelRemoteHost
,
localAddress
:
tunnel
.
localAddress
,
local
:
tunnel
.
tunnelLocalPort
local
Port
:
tunnel
.
tunnelLocalPort
});
}
});
...
...
@@ -56,75 +65,83 @@ export class TunnelModel extends Disposable {
this
.
detected
=
new
Map
();
this
.
_register
(
this
.
tunnelService
.
onTunnelOpened
(
tunnel
=>
{
if
(
!
this
.
forwarded
.
has
(
tunnel
.
tunnelRemotePort
)
&&
tunnel
.
localAddress
)
{
this
.
forwarded
.
set
(
tunnel
.
tunnelRemotePort
,
{
remote
:
tunnel
.
tunnelRemotePort
,
const
key
=
MakeAddress
(
tunnel
.
tunnelRemoteHost
,
tunnel
.
tunnelRemotePort
);
if
((
!
this
.
forwarded
.
has
(
key
))
&&
tunnel
.
localAddress
)
{
this
.
forwarded
.
set
(
key
,
{
remoteHost
:
tunnel
.
tunnelRemoteHost
,
remotePort
:
tunnel
.
tunnelRemotePort
,
localAddress
:
tunnel
.
localAddress
,
local
:
tunnel
.
tunnelLocalPort
,
local
Port
:
tunnel
.
tunnelLocalPort
,
closeable
:
true
});
}
this
.
_onForwardPort
.
fire
(
this
.
forwarded
.
get
(
tunnel
.
tunnelRemotePort
)
!
);
this
.
_onForwardPort
.
fire
(
this
.
forwarded
.
get
(
key
)
!
);
}));
this
.
_register
(
this
.
tunnelService
.
onTunnelClosed
(
remotePort
=>
{
if
(
this
.
forwarded
.
has
(
remotePort
))
{
this
.
forwarded
.
delete
(
remotePort
);
this
.
_onClosePort
.
fire
(
remotePort
);
this
.
_register
(
this
.
tunnelService
.
onTunnelClosed
(
address
=>
{
const
key
=
MakeAddress
(
address
.
host
,
address
.
port
);
if
(
this
.
forwarded
.
has
(
key
))
{
this
.
forwarded
.
delete
(
key
);
this
.
_onClosePort
.
fire
(
address
);
}
}));
}
async
forward
(
remote
:
number
,
local
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
{
if
(
!
this
.
forwarded
.
has
(
remote
))
{
const
tunnel
=
await
this
.
tunnelService
.
openTunnel
(
remote
,
local
);
async
forward
(
remote
:
{
host
:
string
,
port
:
number
},
local
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
{
const
key
=
MakeAddress
(
remote
.
host
,
remote
.
port
);
if
(
!
this
.
forwarded
.
has
(
key
))
{
const
tunnel
=
await
this
.
tunnelService
.
openTunnel
(
remote
.
host
,
remote
.
port
,
local
);
if
(
tunnel
&&
tunnel
.
localAddress
)
{
const
newForward
:
Tunnel
=
{
remote
:
tunnel
.
tunnelRemotePort
,
local
:
tunnel
.
tunnelLocalPort
,
remoteHost
:
tunnel
.
tunnelRemoteHost
,
remotePort
:
tunnel
.
tunnelRemotePort
,
localPort
:
tunnel
.
tunnelLocalPort
,
name
:
name
,
closeable
:
true
,
localAddress
:
tunnel
.
localAddress
};
this
.
forwarded
.
set
(
remote
,
newForward
);
this
.
forwarded
.
set
(
key
,
newForward
);
this
.
_onForwardPort
.
fire
(
newForward
);
return
tunnel
;
}
}
}
name
(
remote
:
number
,
name
:
string
)
{
if
(
this
.
forwarded
.
has
(
remote
))
{
this
.
forwarded
.
get
(
remote
)
!
.
name
=
name
;
this
.
_onPortName
.
fire
(
remote
);
}
else
if
(
this
.
detected
.
has
(
remote
))
{
this
.
detected
.
get
(
remote
)
!
.
name
=
name
;
this
.
_onPortName
.
fire
(
remote
);
name
(
host
:
string
,
port
:
number
,
name
:
string
)
{
const
key
=
MakeAddress
(
host
,
port
);
if
(
this
.
forwarded
.
has
(
key
))
{
this
.
forwarded
.
get
(
key
)
!
.
name
=
name
;
this
.
_onPortName
.
fire
({
host
,
port
});
}
else
if
(
this
.
detected
.
has
(
key
))
{
this
.
detected
.
get
(
key
)
!
.
name
=
name
;
this
.
_onPortName
.
fire
({
host
,
port
});
}
}
async
close
(
remote
:
number
):
Promise
<
void
>
{
return
this
.
tunnelService
.
closeTunnel
(
remote
);
async
close
(
host
:
string
,
port
:
number
):
Promise
<
void
>
{
return
this
.
tunnelService
.
closeTunnel
(
host
,
port
);
}
address
(
remote
:
number
):
string
|
undefined
{
return
(
this
.
forwarded
.
get
(
remote
)
||
this
.
detected
.
get
(
remote
))?.
localAddress
;
address
(
host
:
string
,
port
:
number
):
string
|
undefined
{
const
key
=
MakeAddress
(
host
,
port
);
return
(
this
.
forwarded
.
get
(
key
)
||
this
.
detected
.
get
(
key
))?.
localAddress
;
}
addDetected
(
tunnels
:
{
remote
:
{
port
:
number
,
host
:
string
},
localAddress
:
string
}[]):
void
{
tunnels
.
forEach
(
tunnel
=>
{
this
.
detected
.
set
(
tunnel
.
remote
.
port
,
{
remote
:
tunnel
.
remote
.
port
,
this
.
detected
.
set
(
MakeAddress
(
tunnel
.
remote
.
host
,
tunnel
.
remote
.
port
),
{
remoteHost
:
tunnel
.
remote
.
host
,
remotePort
:
tunnel
.
remote
.
port
,
localAddress
:
tunnel
.
localAddress
,
closeable
:
false
});
});
}
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
):
void
{
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
):
void
{
this
.
_candidateFinder
=
finder
;
}
get
candidates
():
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
{
get
candidates
():
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
{
if
(
this
.
_candidateFinder
)
{
return
this
.
_candidateFinder
();
}
...
...
@@ -138,13 +155,13 @@ export interface IRemoteExplorerService {
targetType
:
string
;
readonly
helpInformation
:
HelpInformation
[];
readonly
tunnelModel
:
TunnelModel
;
onDidChangeEditable
:
Event
<
number
|
undefined
>
;
setEditable
(
remote
:
number
|
undefined
,
data
:
IEditableData
|
null
):
void
;
getEditableData
(
remote
:
number
|
undefined
):
IEditableData
|
undefined
;
forward
(
remote
:
number
,
local
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
;
close
(
remote
:
number
):
Promise
<
void
>
;
onDidChangeEditable
:
Event
<
{
host
:
string
,
port
:
number
|
undefined
}
>
;
setEditable
(
remote
Host
:
string
|
undefined
,
remotePort
:
number
|
undefined
,
data
:
IEditableData
|
null
):
void
;
getEditableData
(
remote
Host
:
string
|
undefined
,
remotePort
:
number
|
undefined
):
IEditableData
|
undefined
;
forward
(
remote
:
{
host
:
string
,
port
:
number
},
localPort
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
;
close
(
remote
:
{
host
:
string
,
port
:
number
}
):
Promise
<
void
>
;
addDetected
(
tunnels
:
{
remote
:
{
port
:
number
,
host
:
string
},
localAddress
:
string
}[]
|
undefined
):
void
;
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
):
void
;
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
):
void
;
}
export
interface
HelpInformation
{
...
...
@@ -189,9 +206,9 @@ class RemoteExplorerService implements IRemoteExplorerService {
public
readonly
onDidChangeTargetType
:
Event
<
string
>
=
this
.
_onDidChangeTargetType
.
event
;
private
_helpInformation
:
HelpInformation
[]
=
[];
private
_tunnelModel
:
TunnelModel
;
private
_editable
:
{
remote
:
number
|
undefined
,
data
:
IEditableData
}
|
undefined
;
private
readonly
_onDidChangeEditable
:
Emitter
<
number
|
undefined
>
=
new
Emitter
();
public
readonly
onDidChangeEditable
:
Event
<
number
|
undefined
>
=
this
.
_onDidChangeEditable
.
event
;
private
_editable
:
{
remote
Host
:
string
,
remotePort
:
number
|
undefined
,
data
:
IEditableData
}
|
undefined
;
private
readonly
_onDidChangeEditable
:
Emitter
<
{
host
:
string
,
port
:
number
|
undefined
}
>
=
new
Emitter
();
public
readonly
onDidChangeEditable
:
Event
<
{
host
:
string
,
port
:
number
|
undefined
}
>
=
this
.
_onDidChangeEditable
.
event
;
constructor
(
@
IStorageService
private
readonly
storageService
:
IStorageService
,
...
...
@@ -246,12 +263,12 @@ class RemoteExplorerService implements IRemoteExplorerService {
return
this
.
_tunnelModel
;
}
forward
(
remote
:
number
,
local
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
{
forward
(
remote
:
{
host
:
string
,
port
:
number
}
,
local
?:
number
,
name
?:
string
):
Promise
<
RemoteTunnel
|
void
>
{
return
this
.
tunnelModel
.
forward
(
remote
,
local
,
name
);
}
close
(
remote
:
number
):
Promise
<
void
>
{
return
this
.
tunnelModel
.
close
(
remote
);
close
(
remote
:
{
host
:
string
,
port
:
number
}
):
Promise
<
void
>
{
return
this
.
tunnelModel
.
close
(
remote
.
host
,
remote
.
port
);
}
addDetected
(
tunnels
:
{
remote
:
{
port
:
number
,
host
:
string
},
localAddress
:
string
}[]
|
undefined
):
void
{
...
...
@@ -260,20 +277,21 @@ class RemoteExplorerService implements IRemoteExplorerService {
}
}
setEditable
(
remote
:
number
|
undefined
,
data
:
IEditableData
|
null
):
void
{
setEditable
(
remote
Host
:
string
,
remotePort
:
number
|
undefined
,
data
:
IEditableData
|
null
):
void
{
if
(
!
data
)
{
this
.
_editable
=
undefined
;
}
else
{
this
.
_editable
=
{
remote
,
data
};
this
.
_editable
=
{
remote
Host
,
remotePort
,
data
};
}
this
.
_onDidChangeEditable
.
fire
(
remote
);
this
.
_onDidChangeEditable
.
fire
(
{
host
:
remoteHost
,
port
:
remotePort
}
);
}
getEditableData
(
remote
:
number
|
undefined
):
IEditableData
|
undefined
{
return
this
.
_editable
&&
this
.
_editable
.
remote
===
remote
?
this
.
_editable
.
data
:
undefined
;
getEditableData
(
remoteHost
:
string
|
undefined
,
remotePort
:
number
|
undefined
):
IEditableData
|
undefined
{
return
(
this
.
_editable
&&
(
this
.
_editable
.
remotePort
===
remotePort
)
&&
this
.
_editable
.
remoteHost
===
remoteHost
)
?
this
.
_editable
.
data
:
undefined
;
}
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
port
:
number
,
detail
:
string
}[]
>
):
void
{
registerCandidateFinder
(
finder
:
()
=>
Promise
<
{
host
:
string
,
port
:
number
,
detail
:
string
}[]
>
):
void
{
this
.
tunnelModel
.
registerCandidateFinder
(
finder
);
}
...
...
src/vs/workbench/services/remote/node/tunnelService.ts
浏览文件 @
8e2b3047
...
...
@@ -103,9 +103,9 @@ export class TunnelService implements ITunnelService {
private
_onTunnelOpened
:
Emitter
<
RemoteTunnel
>
=
new
Emitter
();
public
onTunnelOpened
:
Event
<
RemoteTunnel
>
=
this
.
_onTunnelOpened
.
event
;
private
_onTunnelClosed
:
Emitter
<
number
>
=
new
Emitter
();
public
onTunnelClosed
:
Event
<
number
>
=
this
.
_onTunnelClosed
.
event
;
private
readonly
_tunnels
=
new
Map
<
/*
port */
number
,
{
refcount
:
number
,
readonly
value
:
Promise
<
RemoteTunnel
>
}
>
();
private
_onTunnelClosed
:
Emitter
<
{
host
:
string
,
port
:
number
}
>
=
new
Emitter
();
public
onTunnelClosed
:
Event
<
{
host
:
string
,
port
:
number
}
>
=
this
.
_onTunnelClosed
.
event
;
private
readonly
_tunnels
=
new
Map
<
/*
host*/
string
,
Map
<
/* port */
number
,
{
refcount
:
number
,
readonly
value
:
Promise
<
RemoteTunnel
>
}
>
>
();
private
_tunnelProvider
:
ITunnelProvider
|
undefined
;
public
constructor
(
...
...
@@ -130,23 +130,32 @@ export class TunnelService implements ITunnelService {
}
public
get
tunnels
():
Promise
<
readonly
RemoteTunnel
[]
>
{
return
Promise
.
all
(
Array
.
from
(
this
.
_tunnels
.
values
()).
map
(
x
=>
x
.
value
));
const
promises
:
Promise
<
RemoteTunnel
>
[]
=
[];
Array
.
from
(
this
.
_tunnels
.
values
()).
forEach
(
portMap
=>
Array
.
from
(
portMap
.
values
()).
forEach
(
x
=>
promises
.
push
(
x
.
value
)));
return
Promise
.
all
(
promises
);
}
dispose
():
void
{
for
(
const
{
value
}
of
this
.
_tunnels
.
values
())
{
value
.
then
(
tunnel
=>
tunnel
.
dispose
());
for
(
const
portMap
of
this
.
_tunnels
.
values
())
{
for
(
const
{
value
}
of
portMap
.
values
())
{
value
.
then
(
tunnel
=>
tunnel
.
dispose
());
}
portMap
.
clear
();
}
this
.
_tunnels
.
clear
();
}
openTunnel
(
remotePort
:
number
,
localPort
:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
openTunnel
(
remote
Host
:
string
|
undefined
,
remote
Port
:
number
,
localPort
:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
const
remoteAuthority
=
this
.
environmentService
.
configuration
.
remoteAuthority
;
if
(
!
remoteAuthority
)
{
return
undefined
;
}
const
resolvedTunnel
=
this
.
retainOrCreateTunnel
(
remoteAuthority
,
remotePort
,
localPort
);
if
(
!
remoteHost
||
(
remoteHost
===
'
127.0.0.1
'
))
{
remoteHost
=
'
localhost
'
;
}
const
resolvedTunnel
=
this
.
retainOrCreateTunnel
(
remoteAuthority
,
remoteHost
,
remotePort
,
localPort
);
if
(
!
resolvedTunnel
)
{
return
resolvedTunnel
;
}
...
...
@@ -165,48 +174,62 @@ export class TunnelService implements ITunnelService {
tunnelLocalPort
:
tunnel
.
tunnelLocalPort
,
localAddress
:
tunnel
.
localAddress
,
dispose
:
()
=>
{
const
existing
=
this
.
_tunnels
.
get
(
tunnel
.
tunnelRemotePort
);
if
(
existing
)
{
existing
.
refcount
--
;
this
.
tryDisposeTunnel
(
tunnel
.
tunnelRemotePort
,
existing
);
const
existingHost
=
this
.
_tunnels
.
get
(
tunnel
.
tunnelRemoteHost
);
if
(
existingHost
)
{
const
existing
=
existingHost
.
get
(
tunnel
.
tunnelRemotePort
);
if
(
existing
)
{
existing
.
refcount
--
;
this
.
tryDisposeTunnel
(
tunnel
.
tunnelRemoteHost
,
tunnel
.
tunnelRemotePort
,
existing
);
}
}
}
};
}
private
async
tryDisposeTunnel
(
remotePort
:
number
,
tunnel
:
{
refcount
:
number
,
readonly
value
:
Promise
<
RemoteTunnel
>
}):
Promise
<
void
>
{
private
async
tryDisposeTunnel
(
remote
Host
:
string
,
remote
Port
:
number
,
tunnel
:
{
refcount
:
number
,
readonly
value
:
Promise
<
RemoteTunnel
>
}):
Promise
<
void
>
{
if
(
tunnel
.
refcount
<=
0
)
{
const
disposePromise
:
Promise
<
void
>
=
tunnel
.
value
.
then
(
tunnel
=>
{
tunnel
.
dispose
();
this
.
_onTunnelClosed
.
fire
(
tunnel
.
tunnelRemotePort
);
this
.
_onTunnelClosed
.
fire
(
{
host
:
tunnel
.
tunnelRemoteHost
,
port
:
tunnel
.
tunnelRemotePort
}
);
});
this
.
_tunnels
.
delete
(
remotePort
);
if
(
this
.
_tunnels
.
has
(
remoteHost
))
{
this
.
_tunnels
.
get
(
remoteHost
)
!
.
delete
(
remotePort
);
}
return
disposePromise
;
}
}
async
closeTunnel
(
remotePort
:
number
):
Promise
<
void
>
{
if
(
this
.
_tunnels
.
has
(
remotePort
))
{
const
value
=
this
.
_tunnels
.
get
(
remotePort
)
!
;
async
closeTunnel
(
remoteHost
:
string
,
remotePort
:
number
):
Promise
<
void
>
{
const
portMap
=
this
.
_tunnels
.
get
(
remoteHost
);
if
(
portMap
&&
portMap
.
has
(
remotePort
))
{
const
value
=
portMap
.
get
(
remotePort
)
!
;
value
.
refcount
=
0
;
await
this
.
tryDisposeTunnel
(
remotePort
,
value
);
await
this
.
tryDisposeTunnel
(
remoteHost
,
remotePort
,
value
);
}
}
private
addTunnelToMap
(
remoteHost
:
string
,
remotePort
:
number
,
tunnel
:
Promise
<
RemoteTunnel
>
)
{
if
(
!
this
.
_tunnels
.
has
(
remoteHost
))
{
this
.
_tunnels
.
set
(
remoteHost
,
new
Map
());
}
this
.
_tunnels
.
get
(
remoteHost
)
!
.
set
(
remotePort
,
{
refcount
:
1
,
value
:
tunnel
});
}
private
retainOrCreateTunnel
(
remoteAuthority
:
string
,
remotePort
:
number
,
localPort
?:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
const
existing
=
this
.
_tunnels
.
get
(
remotePort
);
private
retainOrCreateTunnel
(
remoteAuthority
:
string
,
remoteHost
:
string
,
remotePort
:
number
,
localPort
?:
number
):
Promise
<
RemoteTunnel
>
|
undefined
{
const
portMap
=
this
.
_tunnels
.
get
(
remoteHost
);
const
existing
=
portMap
?
portMap
.
get
(
remotePort
)
:
undefined
;
if
(
existing
)
{
++
existing
.
refcount
;
return
existing
.
value
;
}
if
(
this
.
_tunnelProvider
)
{
const
tunnel
=
this
.
_tunnelProvider
.
forwardPort
({
remote
:
{
host
:
'
localhost
'
,
port
:
remotePort
}
});
const
tunnel
=
this
.
_tunnelProvider
.
forwardPort
({
remote
:
{
host
:
remoteHost
,
port
:
remotePort
}
});
if
(
tunnel
)
{
this
.
_tunnels
.
set
(
remotePort
,
{
refcount
:
1
,
value
:
tunnel
}
);
this
.
addTunnelToMap
(
remoteHost
,
remotePort
,
tunnel
);
}
return
tunnel
;
}
else
{
}
else
if
(
remoteHost
===
'
localhost
'
)
{
const
options
:
IConnectionOptions
=
{
commit
:
product
.
commit
,
socketFactory
:
nodeSocketFactory
,
...
...
@@ -221,9 +244,10 @@ export class TunnelService implements ITunnelService {
};
const
tunnel
=
createRemoteTunnel
(
options
,
remotePort
,
localPort
);
this
.
_tunnels
.
set
(
remotePort
,
{
refcount
:
1
,
value
:
tunnel
}
);
this
.
addTunnelToMap
(
remoteHost
,
remotePort
,
tunnel
);
return
tunnel
;
}
return
undefined
;
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录