org.jetbrains.kotlinx.jupyter.startup.PortsGenerating.kt Maven / Gradle / Ivy
package org.jetbrains.kotlinx.jupyter.startup
import java.io.IOException
import java.net.DatagramSocket
import java.net.ServerSocket
import java.util.concurrent.ConcurrentHashMap
import kotlin.random.Random
object GeneratedPortsHolder {
private val usedPorts: MutableSet = ConcurrentHashMap.newKeySet()
private fun isPortAvailable(port: Int): Boolean {
var tcpSocket: ServerSocket? = null
var udpSocket: DatagramSocket? = null
try {
tcpSocket = ServerSocket(port)
tcpSocket.reuseAddress = true
udpSocket = DatagramSocket(port)
udpSocket.reuseAddress = true
return true
} catch (_: IOException) {
} finally {
tcpSocket?.close()
udpSocket?.close()
}
return false
}
fun addPort(port: Int): Boolean = (port !in usedPorts) && isPortAvailable(port) && usedPorts.add(port)
}
fun randomIntsInRange(rangeStart: Int, rangeEnd: Int, limit: Int = rangeEnd - rangeStart): Sequence {
return generateSequence { Random.nextInt(rangeStart, rangeEnd) }.take(limit)
}
class PortsGenerator(
private val portsToTry: () -> Sequence,
) {
fun randomPort() =
portsToTry().find {
GeneratedPortsHolder.addPort(it)
} ?: throw RuntimeException("No free port found")
companion object
}
fun PortsGenerator.Companion.create(portRangeStart: Int, portRangeEnd: Int) = PortsGenerator { randomIntsInRange(portRangeStart, portRangeEnd) }
fun createRandomKernelPorts() = PortsGenerator.create(32768, 65536)
.let { generator -> createKernelPorts { generator.randomPort() } }