Skip to content

Commit 0e7c17c

Browse files
fix(jetbrains): avoid connection loops
1 parent db6f5ed commit 0e7c17c

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

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

Lines changed: 26 additions & 2 deletions
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,6 +31,7 @@ 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
3537
import io.gitpod.gitpodprotocol.api.entities.WorkspaceInstance
@@ -49,7 +51,7 @@ import kotlin.coroutines.coroutineContext
4951

5052
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
5153
class GitpodConnectionProvider : GatewayConnectionProvider {
52-
54+
private val activeConnections = ConcurrentHashMap<String, Boolean>()
5355
private val gitpod = service<GitpodConnectionService>()
5456

5557
private val httpClient = HttpClient.newBuilder()
@@ -58,7 +60,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
5860

5961
private val jacksonMapper = jacksonObjectMapper()
6062
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
61-
63+
6264
override suspend fun connect(
6365
parameters: Map<String, String>,
6466
requestor: ConnectionRequestor
@@ -74,6 +76,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
7476
parameters["workspaceId"]!!,
7577
parameters["backendPort"]
7678
)
79+
7780
val client = gitpod.obtainClient(connectParams.gitpodHost)
7881
val connectionLifetime = Lifetime.Eternal.createNested()
7982
val updates = client.listenToWorkspace(connectionLifetime, connectParams.workspaceId)
@@ -144,6 +147,24 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
144147
connectionPanel.repaint()
145148
}
146149

150+
val connectionKeyId = "${connectParams.gitpodHost}-${connectParams.workspaceId}-${connectParams.backendPort}"
151+
152+
if (activeConnections.containsKey(connectionKeyId)) {
153+
val message = "You are trying to connect to a workspace that has a session already open"
154+
val title = "Oops"
155+
val okButton = Messages.getOkButton()
156+
val options = arrayOf(okButton)
157+
val defaultIndex = 0
158+
val icon = Messages.getWarningIcon()
159+
Messages.showDialog(message, title, options, defaultIndex, icon)
160+
161+
val errMessage = "A connection to the same workspace already exists: $connectionKeyId"
162+
thisLogger().warn(errMessage)
163+
throw IllegalStateException(errMessage)
164+
} else {
165+
activeConnections.putIfAbsent(connectionKeyId, true)
166+
}
167+
147168
GlobalScope.launch {
148169
var thinClient: ThinClientHandle? = null
149170
var thinClientJob: Job? = null
@@ -219,6 +240,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
219240
val sshHostUrl = URL(update.ideUrl.replace(update.workspaceId, "${update.workspaceId}.ssh"));
220241
val hostKeys = resolveHostKeys(updatedIdeUrl, connectParams)
221242
if (hostKeys.isNullOrEmpty()) {
243+
activeConnections.remove(connectionKeyId)
222244
setErrorMessage("${connectParams.gitpodHost} installation does not allow SSH access, public keys cannot be found")
223245
return@launch
224246
}
@@ -227,6 +249,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
227249
resolveCredentials(sshHostUrl, update.workspaceId, ownerToken, hostKeys)
228250
val joinLink = resolveJoinLink(updatedIdeUrl, ownerToken, connectParams)
229251
if (joinLink.isNullOrEmpty()) {
252+
activeConnections.remove(connectionKeyId)
230253
setErrorMessage("failed to fetch JetBrains Gateway Join Link.")
231254
return@launch
232255
}
@@ -239,6 +262,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
239262
clientHandle.clientClosed.advise(connectionLifetime) {
240263
application.invokeLater {
241264
connectionLifetime.terminate()
265+
activeConnections.remove(connectionKeyId)
242266
}
243267
}
244268
clientHandle.onClientPresenceChanged.advise(connectionLifetime) {

0 commit comments

Comments
 (0)