import lyng.io.net

val host = "127.0.0.1"
val clientCount = 1000
val clientWindow = 128
val server = Net.tcpListen(0, host, clientWindow, true)
val port = server.localAddress().port

fun payloadFor(index: Int) = "$index:${Random.nextInt()}:${Random.nextInt()}"

val serverJob = launch {
    try {
        while (true) {
            val client = server.accept()
            launch {
                try {
                    client.readLine()?.let { source ->
                        client.writeUtf8("pong: $source\n")
                        client.flush()
                    }
                } finally {
                    client.close()
                }
            }
        }
    } catch (e) {
        if (server.isOpen()) {
            throw e
        }
    } finally {
        if (server.isOpen()) {
            server.close()
        }
    }
}

var completed = 0
for (batchStart in 0..<clientCount step clientWindow) {
    val batchEnd = if (batchStart + clientWindow < clientCount) batchStart + clientWindow else clientCount
    val replies = (batchStart..<batchEnd).map { index ->
        val payload = payloadFor(index)
        launch {
            val socket = Net.tcpConnect(host, port) as TcpSocket
            try {
                socket.writeUtf8(payload + "\n")
                socket.flush()
                val reply = socket.readLine()
                assertEquals("pong: $payload", reply)
            } finally {
                socket.close()
            }
        }
    }.joinAll()
    completed += replies.size
}

assertEquals(clientCount, completed)
server.close()
serverJob.await()
println("OK: $clientCount concurrent tcp clients")
