fix: download server timeout

This commit is contained in:
rhunk
2023-08-05 11:13:30 +02:00
parent ddfa89f4b4
commit e6e75123f8

View File

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