From 5b13eb5ece73990f9fddf84d5200f6b0c88db1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20R=C3=BCmpelein?= Date: Sat, 25 Sep 2021 13:22:34 +0200 Subject: [PATCH] Few cleanups --- .../kotlin/de/pheerai/buzzer/Application.kt | 6 +- .../de/pheerai/buzzer/clients/adminClient.kt | 21 +++ .../de/pheerai/buzzer/clients/playerClient.kt | 34 +++++ .../de/pheerai/buzzer/data/SessionStorage.kt | 14 ++ .../buzzer/handlers/handleGameMasterSocket.kt | 20 +++ .../buzzer/handlers/handlePlayerSocket.kt | 22 +++ .../de/pheerai/buzzer/plugins/Sockets.kt | 128 ------------------ .../de/pheerai/buzzer/routing/setupRoutes.kt | 52 +++++++ .../de/pheerai/buzzer/setup/setupPlugins.kt | 7 + .../de/pheerai/buzzer/setup/webSockets.kt | 15 ++ 10 files changed, 189 insertions(+), 130 deletions(-) create mode 100644 src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/handlers/handleGameMasterSocket.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/handlers/handlePlayerSocket.kt delete mode 100644 src/main/kotlin/de/pheerai/buzzer/plugins/Sockets.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt create mode 100644 src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt diff --git a/src/main/kotlin/de/pheerai/buzzer/Application.kt b/src/main/kotlin/de/pheerai/buzzer/Application.kt index 8a71b74..c48ab2b 100644 --- a/src/main/kotlin/de/pheerai/buzzer/Application.kt +++ b/src/main/kotlin/de/pheerai/buzzer/Application.kt @@ -1,11 +1,13 @@ package de.pheerai.buzzer -import de.pheerai.buzzer.plugins.* +import de.pheerai.buzzer.routing.configureRoutes +import de.pheerai.buzzer.setup.setupPlugins import io.ktor.server.engine.* import io.ktor.server.netty.* fun main() { embeddedServer(Netty, port = 8888, host = "0.0.0.0") { - configureSockets() + setupPlugins() + configureRoutes() }.start(wait = true) } diff --git a/src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt b/src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt new file mode 100644 index 0000000..b0bb01d --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/clients/adminClient.kt @@ -0,0 +1,21 @@ +package de.pheerai.buzzer.clients + +import kotlinx.html.* + +fun HTML.createAdminDocument() { + head { + meta { charset = "UTF-8" } + title { +"JS Client" } + script { src = "https://code.jquery.com/jquery-3.6.0.min.js" } + script { src = "/assets/adminClient.js" } + } + body { + ol { + id = "usernames" + } + button { + onClick = "resetReceived()" + +"Reset" + } + } +} diff --git a/src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt b/src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt new file mode 100644 index 0000000..487bc68 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/clients/playerClient.kt @@ -0,0 +1,34 @@ +package de.pheerai.buzzer.clients + +import kotlinx.html.* + +fun HTML.createPlayerDocument() { + head { + meta { charset = "UTF-8" } + title { +"JS Client" } + link( + href = "/assets/player.css", + rel = "stylesheet", + type = "text/css" + ) + script { src = "https://code.jquery.com/jquery-3.6.0.min.js" } + script { src = "/assets/playerClient.js" } + } + body { + div(classes = "parent") { + attributes["foo"] = "bar" + div(classes = "input") { + label { +"Player" } + div(classes = "bumper") {} + input { + id = "username" + placeholder = "" + } + } + button(classes = "submit") { + onClick = "sendUsername()" + +"I know that!" + } + } + } +} diff --git a/src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt b/src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt new file mode 100644 index 0000000..2fc1cb4 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/data/SessionStorage.kt @@ -0,0 +1,14 @@ +package de.pheerai.buzzer.data + +import java.util.* + +object SessionStorage { + val playerSessions = synchronisedCollectionOf() + val gameMasterSessions = synchronisedCollectionOf() +} + +fun synchronisedCollectionOf(vararg data: T): MutableCollection { + val list = LinkedList() + list.addAll(data) + return Collections.synchronizedCollection(list) +} diff --git a/src/main/kotlin/de/pheerai/buzzer/handlers/handleGameMasterSocket.kt b/src/main/kotlin/de/pheerai/buzzer/handlers/handleGameMasterSocket.kt new file mode 100644 index 0000000..8c07644 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/handlers/handleGameMasterSocket.kt @@ -0,0 +1,20 @@ +package de.pheerai.buzzer.handlers + +import de.pheerai.buzzer.data.GameMasterSocket +import de.pheerai.buzzer.data.SessionStorage +import io.ktor.http.cio.websocket.* +import kotlinx.coroutines.isActive + +suspend fun WebSocketSession.handleGameMasterSocket() { + SessionStorage.gameMasterSessions.add(GameMasterSocket(this)) + for (frame in incoming) { + when (frame) { + is Frame.Text -> { + val text = frame.readText() + SessionStorage.playerSessions.filter { it.session.isActive } + .forEach { it.session.send(text) } + } + else -> {} + } + } +} diff --git a/src/main/kotlin/de/pheerai/buzzer/handlers/handlePlayerSocket.kt b/src/main/kotlin/de/pheerai/buzzer/handlers/handlePlayerSocket.kt new file mode 100644 index 0000000..f300dd8 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/handlers/handlePlayerSocket.kt @@ -0,0 +1,22 @@ +package de.pheerai.buzzer.handlers + +import de.pheerai.buzzer.data.PlayerSocket +import de.pheerai.buzzer.data.SessionStorage +import io.ktor.http.cio.websocket.* +import kotlinx.coroutines.isActive +import org.slf4j.Logger + +suspend fun WebSocketSession.handlePlayerSocket(log: Logger) { + SessionStorage.playerSessions.add(PlayerSocket(this)) + for (frame in incoming) { + when (frame) { + is Frame.Text -> { + val text = frame.readText() + log.info("Username: $text") + SessionStorage.gameMasterSessions.filter { it.session.isActive } + .forEach { it.session.send(text) } + } + else -> {} + } + } +} diff --git a/src/main/kotlin/de/pheerai/buzzer/plugins/Sockets.kt b/src/main/kotlin/de/pheerai/buzzer/plugins/Sockets.kt deleted file mode 100644 index 5e430eb..0000000 --- a/src/main/kotlin/de/pheerai/buzzer/plugins/Sockets.kt +++ /dev/null @@ -1,128 +0,0 @@ -package de.pheerai.buzzer.plugins - -import de.pheerai.buzzer.data.GameMasterSocket -import de.pheerai.buzzer.data.PlayerSocket -import io.ktor.application.* -import io.ktor.html.* -import io.ktor.http.cio.websocket.* -import io.ktor.http.content.* -import io.ktor.routing.* -import io.ktor.websocket.* -import kotlinx.coroutines.isActive -import kotlinx.html.* -import java.time.Duration -import java.util.* - -fun Application.configureSockets() { - install(WebSockets) { - pingPeriod = Duration.ofSeconds(15) - timeout = Duration.ofSeconds(15) - maxFrameSize = Long.MAX_VALUE - masking = false - } - - routing { - val playerSessions = Collections.synchronizedCollection(LinkedList()) - val gameMasterSessions = Collections.synchronizedCollection(LinkedList()) - - static("/assets") { - resources("css") - resources("js") - } - - get("/") { - call.respondHtml { - createPlayerDocument() - } - } - - get("/client/player") { - call.respondHtml { - createPlayerDocument() - } - } - - get("/client/master") { - call.respondHtml { - createAdminDocument() - } - } - - webSocket("/socket/player") { - playerSessions.add(PlayerSocket(this)) - for (frame in incoming) { - when (frame) { - is Frame.Text -> { - val text = frame.readText() - log.info("Username: $text") - gameMasterSessions.filter { it.session.isActive } - .forEach { it.session.send(text) } - } - else -> {} - } - } - } - - webSocket("/socket/master") { - gameMasterSessions.add(GameMasterSocket(this)) - for (frame in incoming) { - when (frame) { - is Frame.Text -> { - val text = frame.readText() - playerSessions.filter { it.session.isActive } - .forEach { it.session.send(text) } - } - else -> {} - } - } - } - } -} - -fun HTML.createPlayerDocument() { - head { - meta { charset = "UTF-8" } - title { +"JS Client" } - link( - href = "/assets/player.css", - rel = "stylesheet", - type = "text/css" - ) - script { src = "https://code.jquery.com/jquery-3.6.0.min.js" } - script { src = "/assets/playerClient.js" } - } - body { - div(classes = "parent") { - div(classes = "input") { - label { +"Player" } - div(classes = "bumper") {} - input { - id = "username" - placeholder = "" - } - } - button(classes = "submit") { - onClick = "sendUsername()" - +"I know that!" - } - } - } -} - -fun HTML.createAdminDocument() { - head { - meta { charset = "UTF-8" } - title { +"JS Client" } - script { src = "https://code.jquery.com/jquery-3.6.0.min.js" } - script { src = "/assets/adminClient.js" } - } - body { - ol { - id = "usernames" - } - button { - onClick = "resetReceived()" - +"Reset" - } - } -} diff --git a/src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt b/src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt new file mode 100644 index 0000000..bbe5e51 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/routing/setupRoutes.kt @@ -0,0 +1,52 @@ +package de.pheerai.buzzer.routing + +import de.pheerai.buzzer.clients.createAdminDocument +import de.pheerai.buzzer.clients.createPlayerDocument +import de.pheerai.buzzer.handlers.handleGameMasterSocket +import de.pheerai.buzzer.handlers.handlePlayerSocket +import io.ktor.application.* +import io.ktor.html.* +import io.ktor.http.content.* +import io.ktor.routing.* +import io.ktor.websocket.* +import org.slf4j.Logger + +fun Application.configureRoutes() { + routing { + assetRoutes() + clientRoutes() + websocketRoutes(log) + } +} + +private fun Routing.websocketRoutes(log: Logger) { + webSocket("/socket/player") { handlePlayerSocket(log) } + webSocket("/socket/master") { handleGameMasterSocket() } +} + +private fun Routing.clientRoutes() { + get("/") { + call.respondHtml { + createPlayerDocument() + } + } + + get("/client/player") { + call.respondHtml { + createPlayerDocument() + } + } + + get("/client/master") { + call.respondHtml { + createAdminDocument() + } + } +} + +private fun Routing.assetRoutes() { + static("/assets") { + resources("css") + resources("js") + } +} diff --git a/src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt b/src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt new file mode 100644 index 0000000..16cc08b --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/setup/setupPlugins.kt @@ -0,0 +1,7 @@ +package de.pheerai.buzzer.setup + +import io.ktor.application.* + +fun Application.setupPlugins() { + installWebSockets() +} diff --git a/src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt b/src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt new file mode 100644 index 0000000..2d10664 --- /dev/null +++ b/src/main/kotlin/de/pheerai/buzzer/setup/webSockets.kt @@ -0,0 +1,15 @@ +package de.pheerai.buzzer.setup + +import io.ktor.application.* +import io.ktor.http.cio.websocket.* +import io.ktor.websocket.* +import java.time.Duration + +fun Application.installWebSockets() { + install(WebSockets) { + pingPeriod = Duration.ofSeconds(15) + timeout = Duration.ofSeconds(15) + maxFrameSize = Long.MAX_VALUE + masking = false + } +}