commit e6e75123f85f21e4405769ff97c7712505be533e
parent ddfa89f4b4e3c5271f6dc218470b93090d781604
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat,  5 Aug 2023 11:13:30 +0200

fix: download server timeout

Diffstat:
Mcore/src/main/kotlin/me/rhunk/snapenhance/util/download/DownloadServer.kt | 39+++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/download/DownloadServer.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/download/DownloadServer.kt @@ -2,6 +2,8 @@ package me.rhunk.snapenhance.util.download import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import me.rhunk.snapenhance.Logger import java.io.BufferedReader @@ -10,16 +12,20 @@ import java.io.InputStreamReader import java.io.PrintWriter import java.net.ServerSocket import java.net.Socket -import java.net.SocketTimeoutException +import java.net.SocketException import java.util.Locale import java.util.StringTokenizer import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ThreadLocalRandom +import kotlin.random.Random class DownloadServer( private val timeout: Int = 10000 ) { - private val port = ThreadLocalRandom.current().nextInt(10000, 65535) + private val port = Random.nextInt(10000, 65535) + + private val coroutineScope = CoroutineScope(Dispatchers.IO) + private var timeoutJob: Job? = null + private var socketJob: Job? = null private val cachedData = ConcurrentHashMap<String, Pair<InputStream, Long>>() private var serverSocket: ServerSocket? = null @@ -30,27 +36,36 @@ class DownloadServer( return } - CoroutineScope(Dispatchers.IO).launch { + coroutineScope.launch(Dispatchers.IO) { Logger.debug("starting download server on port $port") serverSocket = ServerSocket(port) - serverSocket!!.soTimeout = timeout callback(this@DownloadServer) while (!serverSocket!!.isClosed) { try { val socket = serverSocket!!.accept() - launch(Dispatchers.IO) { + timeoutJob?.cancel() + launch { handleRequest(socket) + timeoutJob = launch { + delay(timeout.toLong()) + Logger.debug("download server closed due to timeout") + runCatching { + socketJob?.cancel() + socket.close() + serverSocket?.close() + }.onFailure { + Logger.error(it) + } + } } - } catch (e: SocketTimeoutException) { - serverSocket?.close() - serverSocket = null - Logger.debug("download server closed") + } catch (e: SocketException) { + Logger.debug("download server timed out") break; - } catch (e: Exception) { + } catch (e: Throwable) { Logger.error("failed to handle request", e) } } - } + }.also { socketJob = it } } fun close() {