Skip to content

Commit

Permalink
NOVA - Better connection handling
Browse files Browse the repository at this point in the history
Fixes #305
  • Loading branch information
elmot committed Jul 27, 2024
1 parent 1954391 commit 1c3ed5c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
build/
venv/
tmp/
out/
43 changes: 22 additions & 21 deletions src/main/kotlin/com/jetbrains/micropython/nova/WebSocketComm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ with open('$fullName', 'wb') as f:
inner class MpyWebSocketClient(uri: URI) : WebSocketClient(uri) {
init {
isTcpNoDelay = true
connectionLostTimeout = 0
}

override fun onOpen(handshakedata: ServerHandshake) = Unit //Nothing to do
Expand Down Expand Up @@ -257,47 +258,47 @@ with open('$fullName', 'wb') as f:
connected = false
ttySuspended = true
client?.close()
client = MpyWebSocketClient(uri).apply {
connectBlocking()
client = MpyWebSocketClient(uri).also { newClient ->
newClient.connectBlocking()
try {
withTimeout(TIMEOUT.toLong()) {
while (true) {
while (newClient.isOpen) {
when {
offTtyBuffer.length < PASSWORD_PROMPT.length -> delay(SHORT_DELAY)
offTtyBuffer.length > PASSWORD_PROMPT.length * 2 -> {
offTtyBuffer.setLength(PASSWORD_PROMPT.length * 2)
throw ConnectException("Password exchange error. Received prompt: $offTtyBuffer")
}

else -> {
if (offTtyBuffer.toString().contains(PASSWORD_PROMPT)) {
offTtyBuffer.clear()
send("$password\n")
while (!connected) {
when {
offTtyBuffer.contains(LOGIN_SUCCESS) -> connected = true
offTtyBuffer.contains(LOGIN_FAIL) -> throw ConnectException("Access denied")
else -> delay(SHORT_DELAY)
}
}
} else {
throw ConnectException("Password exchange error. Received prompt: $offTtyBuffer")
}
return@withTimeout
offTtyBuffer.toString().contains(PASSWORD_PROMPT) -> break
else -> throw ConnectException("Password exchange error. Received prompt: $offTtyBuffer")
}
}
offTtyBuffer.clear()
newClient.send("$password\n")
while (!connected && newClient.isOpen) {
when {
offTtyBuffer.contains(LOGIN_SUCCESS) -> connected = true
offTtyBuffer.contains(LOGIN_FAIL) -> throw ConnectException("Access denied")
else -> delay(SHORT_DELAY)
}
}
ttySuspended = false
}
} catch (e: TimeoutCancellationException) {
try {
newClient.close()
} catch (_: IOException) {}
throw ConnectException("Password exchange timeout. Received prompt: $offTtyBuffer")
} finally {
offTtyBuffer.clear()
}
}

}
}


fun ping() {
if(isConnected()) {
client?.sendPing()
}
}
}
26 changes: 26 additions & 0 deletions src/test/kotlin/com/jetbrains/micropython/nova/RealConnect.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jetbrains.micropython.nova

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.*
Expand Down Expand Up @@ -84,4 +85,29 @@ class RealConnect {
}
}

@Test
@Disabled
fun longRunConnection() {
runBlocking {
comm.connect(URI.create(URL), PASSWORD)
assertTrue(comm.isConnected())
assertFalse(comm.isTtySuspended())
println("Connected")
launch {
while (comm.isConnected()) {
delay(20000)
println("ping")
comm.ping()
}
}
val start = System.currentTimeMillis()
while (comm.isConnected()) {
delay(1000)
println("Still alive")
}
println("Disconnect time: ${System.currentTimeMillis() - start}ms")

}
}

}

0 comments on commit 1c3ed5c

Please sign in to comment.