4
4
5
5
package io.gitpod.jetbrains.remote.latest
6
6
7
+ import com.intellij.openapi.Disposable
8
+ import com.intellij.openapi.client.ClientProjectSession
7
9
import com.intellij.openapi.components.service
8
10
import com.intellij.openapi.diagnostic.thisLogger
9
- import com.intellij.openapi.project.Project
11
+ import com.intellij.openapi.util.Disposer
10
12
import com.intellij.remoteDev.util.onTerminationOrNow
11
13
import com.intellij.util.application
12
- import com.jetbrains.codeWithMe.model.RdPortType
14
+ import com.jetbrains.rd.platform. codeWithMe.portForwarding.*
13
15
import com.jetbrains.rd.platform.util.lifetime
14
16
import com.jetbrains.rd.util.lifetime.LifetimeStatus
15
- import com.jetbrains.rdserver.portForwarding.ForwardedPortInfo
16
- import com.jetbrains.rdserver.portForwarding.PortForwardingManager
17
- import com.jetbrains.rdserver.portForwarding.remoteDev.PortEventsProcessor
18
17
import io.gitpod.jetbrains.remote.GitpodManager
19
18
import io.gitpod.jetbrains.remote.GitpodPortsService
20
19
import io.gitpod.supervisor.api.Status
@@ -24,14 +23,17 @@ import io.grpc.stub.ClientResponseObserver
24
23
import io.ktor.utils.io.*
25
24
import java.util.concurrent.CompletableFuture
26
25
import java.util.concurrent.TimeUnit
26
+ import javax.swing.Icon
27
27
28
28
@Suppress(" UnstableApiUsage" )
29
- class GitpodPortForwardingService (private val project : Project ) {
29
+ class GitpodPortForwardingService (private val session : ClientProjectSession ) {
30
30
companion object {
31
31
const val FORWARDED_PORT_LABEL = " gitpod"
32
32
}
33
33
34
34
private val portsService = service<GitpodPortsService >()
35
+ private val perClientPortForwardingManager = service<PerClientPortForwardingManager >()
36
+ private val portToDisposableMap = mutableMapOf<Int ,Disposable >()
35
37
36
38
init { start() }
37
39
@@ -42,7 +44,7 @@ class GitpodPortForwardingService(private val project: Project) {
42
44
}
43
45
44
46
private fun observePortsListWhileProjectIsOpen () = application.executeOnPooledThread {
45
- while (project.lifetime.status == LifetimeStatus .Alive ) {
47
+ while (session. project.lifetime.status == LifetimeStatus .Alive ) {
46
48
try {
47
49
observePortsList().get()
48
50
} catch (throwable: Throwable ) {
@@ -70,7 +72,7 @@ class GitpodPortForwardingService(private val project: Project) {
70
72
val portsStatusResponseObserver = object :
71
73
ClientResponseObserver <Status .PortsStatusRequest , Status .PortsStatusResponse > {
72
74
override fun beforeStart (request : ClientCallStreamObserver <Status .PortsStatusRequest >) {
73
- project.lifetime.onTerminationOrNow { request.cancel(" gitpod: Project terminated." , null ) }
75
+ session. project.lifetime.onTerminationOrNow { request.cancel(" gitpod: Project terminated." , null ) }
74
76
}
75
77
override fun onNext (response : Status .PortsStatusResponse ) {
76
78
application.invokeLater { updateForwardedPortsList(response) }
@@ -85,48 +87,88 @@ class GitpodPortForwardingService(private val project: Project) {
85
87
}
86
88
87
89
private fun updateForwardedPortsList (response : Status .PortsStatusResponse ) {
88
- val portForwardingManager = PortForwardingManager .getInstance(project)
89
- val forwardedPortsList = portForwardingManager.getForwardedPortsWithLabel(FORWARDED_PORT_LABEL )
90
+ val forwardedPorts = perClientPortForwardingManager.getPorts(FORWARDED_PORT_LABEL )
90
91
91
92
for (port in response.portsList) {
92
93
val hostPort = port.localPort
93
94
val isServed = port.served
94
- val isForwarded = forwardedPortsList .find { it.hostPort == hostPort } != null
95
+ val isForwarded = forwardedPorts .find { it.hostPortNumber == hostPort } != null
95
96
96
97
if (isServed && ! isForwarded) {
97
- val portEventsProcessor = object : PortEventsProcessor {
98
- override fun onPortForwarded (hostPort : Int , clientPort : Int ) {
99
- portsService.setForwardedPort(hostPort, clientPort)
100
- thisLogger().info(" gitpod: Forwarded port $hostPort to client's port $clientPort ." )
98
+ val exposedPort = perClientPortForwardingManager.exposePort(
99
+ hostPort,
100
+ port.exposed.url,
101
+ setOf (FORWARDED_PORT_LABEL ),
102
+ fun (portPresentation : PortPresentation ) {
103
+ portPresentation.name = port.name
104
+ portPresentation.description = port.description
105
+ portPresentation.icon = null
106
+ portPresentation.tooltip = " Exposed Port"
107
+ }
108
+ )
109
+
110
+ val forwardedPort = perClientPortForwardingManager.forwardPort(
111
+ hostPort,
112
+ PortType .NON_USER_TCP ,
113
+ setOf (FORWARDED_PORT_LABEL ),
114
+ hostPort,
115
+ ClientPortPickingStrategy .REASSIGN_WHEN_BUSY ,
116
+ fun (portPresentation : PortPresentation ) {
117
+ portPresentation.name = port.name
118
+ portPresentation.description = port.description
119
+ portPresentation.icon = null
120
+ portPresentation.tooltip = " Forwarded Port"
121
+ }
122
+ )
123
+
124
+ val forwardedPortListener = object : ForwardedPortListener {
125
+ override fun becameReadOnly (port : ForwardedPort , reason : String? ) {
126
+ thisLogger().warn(" gitpod: becameReadOnly($port , $reason )" )
127
+ }
128
+
129
+ override fun descriptionChanged (port : ForwardedPort , oldDescription : String? , newDescription : String? ) {
130
+ thisLogger().warn(" gitpod: descriptionChanged($port , $oldDescription , $newDescription )" )
101
131
}
102
132
103
- override fun onPortForwardingEnded ( hostPort : Int ) {
104
- thisLogger().info (" gitpod: Finished forwarding port $hostPort . " )
133
+ override fun exposedUrlChanged ( port : ForwardedPort , newUrl : String ) {
134
+ thisLogger().warn (" gitpod: exposedUrlChanged( $ port, $newUrl ) " )
105
135
}
106
136
107
- override fun onPortForwardingFailed (hostPort : Int , reason : String ) {
108
- thisLogger().error(" gitpod: Failed to forward port $hostPort : $reason " )
137
+ override fun iconChanged (port : ForwardedPort , oldIcon : Icon ? , newIcon : Icon ? ) {
138
+ thisLogger().warn(" gitpod: iconChanged($port , $oldIcon , $newIcon )" )
139
+ }
140
+
141
+ override fun nameChanged (port : ForwardedPort , oldName : String? , newName : String? ) {
142
+ thisLogger().warn(" gitpod: nameChanged($port , $oldName , $newName )" )
143
+ }
144
+
145
+ override fun stateChanged (port : ForwardedPort , newState : ClientPortState ) {
146
+ thisLogger().warn(" gitpod: stateChanged($port , $newState )" )
147
+ }
148
+
149
+ override fun tooltipChanged (port : ForwardedPort , oldTooltip : String? , newTooltip : String? ) {
150
+ thisLogger().warn(" gitpod: tooltipChanged($port , $oldTooltip , $newTooltip )" )
109
151
}
110
152
}
111
153
112
- val portInfo = ForwardedPortInfo (
113
- hostPort,
114
- RdPortType .HTTP ,
115
- port.exposed.url,
116
- port.name,
117
- port.description,
118
- setOf (FORWARDED_PORT_LABEL ),
119
- emptyList(),
120
- portEventsProcessor
121
- )
154
+ val portListenerDisposable = portToDisposableMap.getOrPut(hostPort, fun () = Disposer .newDisposable())
122
155
123
- portForwardingManager.forwardPort(portInfo)
156
+ exposedPort.addPortListener(portListenerDisposable, forwardedPortListener)
157
+ forwardedPort.addPortListener(portListenerDisposable, forwardedPortListener)
124
158
}
125
159
126
160
if (! isServed && isForwarded) {
127
- portForwardingManager.removePort(hostPort)
161
+ thisLogger().warn(" hostPort $hostPort stopped being" )
162
+ val portListenerDisposable = portToDisposableMap[hostPort]
163
+ if (portListenerDisposable != null ) {
164
+ portListenerDisposable.dispose()
165
+ portToDisposableMap.remove(hostPort)
166
+ }
167
+ perClientPortForwardingManager.getPorts(hostPort).forEach { portToRemove ->
168
+ perClientPortForwardingManager.removePort(portToRemove)
169
+ }
128
170
portsService.removeForwardedPort(hostPort)
129
- thisLogger().info (" gitpod: Stopped forwarding port $hostPort ." )
171
+ thisLogger().warn (" gitpod: Stopped forwarding port $hostPort ." )
130
172
}
131
173
}
132
174
}
0 commit comments