Skip to content

Commit 60f0428

Browse files
fix(jetbrains): avoid connection loops
1 parent db6f5ed commit 60f0428

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

components/ide/jetbrains/gateway-plugin/src/main/kotlin/io/gitpod/jetbrains/gateway/GitpodConnectionProvider.kt

+33-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.intellij.ide.BrowserUtil
1212
import com.intellij.openapi.components.service
1313
import com.intellij.openapi.diagnostic.thisLogger
1414
import com.intellij.openapi.progress.ProgressManager
15+
import com.intellij.openapi.ui.Messages
1516
import com.intellij.remote.RemoteCredentialsHolder
1617
import com.intellij.ssh.AskAboutHostKey
1718
import com.intellij.ssh.OpenSshLikeHostKeyVerifier
@@ -30,8 +31,10 @@ import com.jetbrains.gateway.api.*
3031
import com.jetbrains.gateway.ssh.ClientOverSshTunnelConnector
3132
import com.jetbrains.gateway.ssh.SshHostTunnelConnector
3233
import com.jetbrains.gateway.thinClientLink.ThinClientHandle
34+
import com.jetbrains.rd.util.ConcurrentHashMap
3335
import com.jetbrains.rd.util.URI
3436
import com.jetbrains.rd.util.lifetime.Lifetime
37+
import com.jetbrains.rd.util.lifetime.LifetimeDefinition
3538
import io.gitpod.gitpodprotocol.api.entities.WorkspaceInstance
3639
import io.gitpod.jetbrains.icons.GitpodIcons
3740
import kotlinx.coroutines.*
@@ -49,7 +52,7 @@ import kotlin.coroutines.coroutineContext
4952

5053
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
5154
class GitpodConnectionProvider : GatewayConnectionProvider {
52-
55+
private val activeConnections = ConcurrentHashMap<String, LifetimeDefinition>()
5356
private val gitpod = service<GitpodConnectionService>()
5457

5558
private val httpClient = HttpClient.newBuilder()
@@ -74,8 +77,34 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
7477
parameters["workspaceId"]!!,
7578
parameters["backendPort"]
7679
)
80+
81+
val connectionKeyId = "${connectParams.gitpodHost}-${connectParams.workspaceId}-${connectParams.backendPort}"
82+
83+
var found = true
84+
val connectionLifetime = activeConnections.computeIfAbsent(connectionKeyId) {
85+
found = false
86+
Lifetime.Eternal.createNested()
87+
}
88+
89+
if (found) {
90+
val message =
91+
"You are trying to connect to a workspace that has a client already open. Check for opened JetBrains clients on your machine"
92+
val title = "${connectParams.workspaceId} (${connectParams.gitpodHost})"
93+
val okButton = Messages.getOkButton()
94+
val options = arrayOf(okButton)
95+
val defaultIndex = 0
96+
val icon = Messages.getWarningIcon()
97+
Messages.showDialog(message, title, options, defaultIndex, icon)
98+
99+
val errMessage = "A connection to the same workspace already exists: $connectionKeyId"
100+
throw IllegalStateException(errMessage)
101+
} else {
102+
connectionLifetime.onTermination {
103+
activeConnections.remove(connectionKeyId)
104+
}
105+
}
106+
77107
val client = gitpod.obtainClient(connectParams.gitpodHost)
78-
val connectionLifetime = Lifetime.Eternal.createNested()
79108
val updates = client.listenToWorkspace(connectionLifetime, connectParams.workspaceId)
80109
val workspace = client.syncWorkspace(connectParams.workspaceId).workspace
81110

@@ -216,7 +245,8 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
216245
thinClientJob = launch {
217246
try {
218247
val updatedIdeUrl = URL(update.ideUrl);
219-
val sshHostUrl = URL(update.ideUrl.replace(update.workspaceId, "${update.workspaceId}.ssh"));
248+
val sshHostUrl =
249+
URL(update.ideUrl.replace(update.workspaceId, "${update.workspaceId}.ssh"));
220250
val hostKeys = resolveHostKeys(updatedIdeUrl, connectParams)
221251
if (hostKeys.isNullOrEmpty()) {
222252
setErrorMessage("${connectParams.gitpodHost} installation does not allow SSH access, public keys cannot be found")

0 commit comments

Comments
 (0)