diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8e58283..4a2303b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "dev.castarr.tv" minSdk = 26 targetSdk = 35 - versionCode = 34 - versionName = "0.11.1" + versionCode = 35 + versionName = "0.11.2" } // Release signing from environment (see ~/.keys/castarr-release.env on the diff --git a/app/src/main/java/dev/castarr/tv/server/ControlServer.kt b/app/src/main/java/dev/castarr/tv/server/ControlServer.kt index 42c2b16..4c4d99c 100644 --- a/app/src/main/java/dev/castarr/tv/server/ControlServer.kt +++ b/app/src/main/java/dev/castarr/tv/server/ControlServer.kt @@ -97,7 +97,12 @@ class ControlServer( fun startServer() { // A busy port must not take the whole app down — the remote is // optional, everything else keeps working. - running = runCatching { start(NanoHTTPD.SOCKET_READ_TIMEOUT, true) } + // NanoHTTPD's 5 s default also applies to the long-lived WebSocket: + // with pings only every 8 s the socket timed out mid-session and the + // remote was thrown out after a few seconds. The timeout still has to + // exist (idle connections must not pin threads), it just has to be + // comfortably longer than the ping interval. + running = runCatching { start(SOCKET_TIMEOUT_MS, true) } .onFailure { Log.w(TAG, "control server unavailable: ${it.javaClass.simpleName}") } .isSuccess if (!running) return @@ -354,6 +359,7 @@ class ControlServer( private companion object { const val TAG = "ControlServer" const val PING_INTERVAL_MS = 8_000L + const val SOCKET_TIMEOUT_MS = 40_000 const val ATTEMPT_WINDOW_MS = 60_000L const val ATTEMPT_MAX = 5 const val MAX_TRACKED_ADDRESSES = 64