From 55587fa9a5c3e4a7d22645ab1a6d79f07ad9c2af Mon Sep 17 00:00:00 2001 From: ProtoByter Date: Mon, 5 Dec 2022 15:59:35 +0000 Subject: [PATCH] Move all tracker code to its own package and switch to Netty Engine instead of embeddedServer --- .../openproximitychat/common/UPnPManager.kt | 25 +++++---- server/build.gradle.kts | 13 +++-- .../{ => tracker}/Application.kt | 41 ++++++++++----- .../{ => tracker}/DatabaseHandler.kt | 2 +- .../{ => tracker}/InstantSerialiser.kt | 2 +- .../{ => tracker}/Requests.kt | 2 +- .../{ => tracker}/UUIDSerialise.kt | 2 +- .../{ => tracker}/Versions.kt | 2 +- server/src/main/resources/application.yaml | 6 +++ .../{ => tracker}/ApplicationKtTest.kt | 52 ++----------------- .../{ => tracker}/DatabaseHandlerTest.kt | 2 +- 11 files changed, 64 insertions(+), 85 deletions(-) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/Application.kt (81%) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/DatabaseHandler.kt (98%) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/InstantSerialiser.kt (94%) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/Requests.kt (92%) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/UUIDSerialise.kt (94%) rename server/src/main/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/Versions.kt (95%) create mode 100644 server/src/main/resources/application.yaml rename server/src/test/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/ApplicationKtTest.kt (87%) rename server/src/test/kotlin/org/muellerssoftware/openproximitychat/{ => tracker}/DatabaseHandlerTest.kt (98%) diff --git a/common/src/main/kotlin/org/muellerssoftware/openproximitychat/common/UPnPManager.kt b/common/src/main/kotlin/org/muellerssoftware/openproximitychat/common/UPnPManager.kt index b9a10c6..088278b 100644 --- a/common/src/main/kotlin/org/muellerssoftware/openproximitychat/common/UPnPManager.kt +++ b/common/src/main/kotlin/org/muellerssoftware/openproximitychat/common/UPnPManager.kt @@ -5,10 +5,12 @@ import kotlinx.coroutines.* import org.bitlet.weupnp.GatewayDevice import org.bitlet.weupnp.GatewayDiscover +data class MappedPort(val port: Int, val protocol: String) + object UPnPManager { - var gateway: GatewayDevice? = null - val mappedPorts = mutableMapOf() - var discoveryJob: Job = Job() + private var gateway: GatewayDevice? = null + private val mappedPorts = mutableMapOf() + private var discoveryJob: Job = Job() init { runBlocking { @@ -23,7 +25,8 @@ object UPnPManager { for (i in 0..9) { Logging.info("Searching for UPnP gateway... (Attempt ${i + 1})") gatewayDiscoverer.discover() - if (gatewayDiscoverer.getValidGateway() != null) { + gateway = GatewayDevice() + if (gatewayDiscoverer.validGateway != null) { gateway = gatewayDiscoverer.validGateway break } @@ -38,29 +41,29 @@ object UPnPManager { mappedPorts.clear() ports.map { - mapPort(it.key, it.value) + mapPort(it.key, it.value.port, it.value.protocol) } } } - fun mapPort(port: Int) { - mapPort(port, port) + fun mapPort(port: Int, protocol: String = "TCP") { + mapPort(port, port, protocol) } - fun mapPort(internalPort: Int, externalPort: Int) { + fun mapPort(internalPort: Int, externalPort: Int, protocol: String = "TCP") { if (gateway == null) { - mappedPorts.put(internalPort, externalPort) + mappedPorts[internalPort] = MappedPort(externalPort, protocol) } val succeeded = gateway?.addPortMapping(externalPort, internalPort, gateway!!.localAddress.hostAddress, "TCP", "OpenProximityChat mapped port") if (succeeded == true) { - mappedPorts.put(internalPort, externalPort) + mappedPorts[internalPort] = MappedPort(externalPort, protocol) } } fun unMapAll() { mappedPorts.map { - gateway?.deletePortMapping(it.value, "UDP") + gateway?.deletePortMapping(it.value.port, it.value.protocol) } } } \ No newline at end of file diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 53571e0..3fc3521 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -18,7 +18,7 @@ group = "org.muellerssoftware.openproximitychat" version = "0.0.1" application { - mainClass.set("org.muellerssoftware.openproximitychat.ApplicationKt") + mainClass.set("io.ktor.server.netty.EngineMain") val isDevelopment: Boolean = project.ext.has("development") applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") @@ -32,6 +32,7 @@ dependencies { // JUnit testImplementation(platform("org.junit:junit-bom:$junit_version")) testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") // Ktor implementation("io.ktor:ktor-server-core-jvm:$ktor_version") @@ -41,12 +42,11 @@ dependencies { implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version") implementation("io.ktor:ktor-server-auth-jvm:$ktor_version") implementation("io.ktor:ktor-server-netty-jvm:$ktor_version") - implementation("ch.qos.logback:logback-classic:$logback_version") + implementation("io.ktor:ktor-server-config-yaml:$ktor_version") testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") - // UPNP - implementation("org.bitlet:weupnp:$weupnp_version") + // Logging + implementation("ch.qos.logback:logback-classic:$logback_version") // Jetbrains Exposed implementation("org.jetbrains.exposed:exposed-core:$exposed_version") @@ -56,6 +56,9 @@ dependencies { // H2 implementation("com.h2database:h2:$db_version") + + // Common Kotlin + implementation(project(":common")) } tasks { diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Application.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Application.kt similarity index 81% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/Application.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Application.kt index de2c6d7..6ae144e 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Application.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Application.kt @@ -1,26 +1,34 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import io.ktor.server.auth.* -import io.ktor.server.engine.* -import io.ktor.server.netty.* import io.ktor.server.plugins.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* +import org.muellerssoftware.openproximitychat.common.Logging +import org.muellerssoftware.openproximitychat.common.UPnPManager import java.util.* -fun main() { - embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module) - .start(wait = true) -} +fun main(args: Array): Unit = io.ktor.server.netty.EngineMain.main(args) fun Application.module() { + Logging.logger = log + environment.monitor.subscribe(ApplicationStarted) { + log.info("Application started") + UPnPManager.mapPort(this.environment.config.port, "TCP") + } + + environment.monitor.subscribe(ApplicationStopping) { + log.info("Application stopping") + UPnPManager.unMapAll() + } + authentication { - basic("auth") { + basic("basicAuth") { realm = "OpenProximityChat" validate { credentials -> val id = UUID.fromString(credentials.name) @@ -33,6 +41,10 @@ fun Application.module() { } } + install(ContentNegotiation) { + json() + } + routing { get("/info") { call.respondText(""" @@ -78,12 +90,17 @@ fun Application.module() { if (client != null) { call.respond(HttpStatusCode.BadRequest, "Invalid request") } else { - val id = DatabaseHandler.addClient(request.id, request.name,this.call.request.origin.remoteHost+":${this.call.request.origin.port}", request.sampledClients) + val id = DatabaseHandler.addClient( + request.id, + request.name, + this.call.request.origin.remoteHost + ":${this.call.request.origin.port}", + request.sampledClients + ) call.respond(HttpStatusCode.OK, RegisterResponse(id)) } } - authenticate("auth") { + authenticate("basicAuth") { post("/protected/heartbeat") { try { val password = DatabaseHandler.doHeartbeat(call.principal()!!.uuid) @@ -124,8 +141,4 @@ fun Application.module() { } } } - - install(ContentNegotiation) { - json() - } } diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandler.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandler.kt similarity index 98% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandler.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandler.kt index ede9e15..068807b 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandler.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandler.kt @@ -1,6 +1,6 @@ @file:UseSerializers(UUIDAsStringSerializer::class, InstantAsStringSerializer::class) -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/InstantSerialiser.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/InstantSerialiser.kt similarity index 94% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/InstantSerialiser.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/InstantSerialiser.kt index 4146769..55b64ee 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/InstantSerialiser.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/InstantSerialiser.kt @@ -1,4 +1,4 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Requests.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Requests.kt similarity index 92% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/Requests.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Requests.kt index 8ac57b3..f07ab90 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Requests.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Requests.kt @@ -1,6 +1,6 @@ @file:UseSerializers(UUIDAsStringSerializer::class) -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import io.ktor.server.auth.* import kotlinx.serialization.Serializable diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/UUIDSerialise.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/UUIDSerialise.kt similarity index 94% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/UUIDSerialise.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/UUIDSerialise.kt index 977eb68..32c2057 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/UUIDSerialise.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/UUIDSerialise.kt @@ -1,4 +1,4 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer diff --git a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Versions.kt b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Versions.kt similarity index 95% rename from server/src/main/kotlin/org/muellerssoftware/openproximitychat/Versions.kt rename to server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Versions.kt index 718da43..ed93a39 100644 --- a/server/src/main/kotlin/org/muellerssoftware/openproximitychat/Versions.kt +++ b/server/src/main/kotlin/org/muellerssoftware/openproximitychat/tracker/Versions.kt @@ -1,4 +1,4 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import io.ktor.server.application.* diff --git a/server/src/main/resources/application.yaml b/server/src/main/resources/application.yaml new file mode 100644 index 0000000..85abd61 --- /dev/null +++ b/server/src/main/resources/application.yaml @@ -0,0 +1,6 @@ +ktor: + deployment: + port: 0 + application: + modules: + - org.muellerssoftware.openproximitychat.tracker.ApplicationKt.module \ No newline at end of file diff --git a/server/src/test/kotlin/org/muellerssoftware/openproximitychat/ApplicationKtTest.kt b/server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/ApplicationKtTest.kt similarity index 87% rename from server/src/test/kotlin/org/muellerssoftware/openproximitychat/ApplicationKtTest.kt rename to server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/ApplicationKtTest.kt index 3ca96f0..925735f 100644 --- a/server/src/test/kotlin/org/muellerssoftware/openproximitychat/ApplicationKtTest.kt +++ b/server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/ApplicationKtTest.kt @@ -1,4 +1,4 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import io.ktor.client.call.* import io.ktor.client.plugins.contentnegotiation.* @@ -12,7 +12,8 @@ import kotlin.test.Test import kotlin.test.assertEquals class ApplicationKtTest { - val sampledClientsTestVal = listOf(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()) + private val sampledClientsTestVal = listOf(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()) + @Before fun addTestData() { DatabaseHandler.clear() @@ -27,10 +28,6 @@ class ApplicationKtTest { } } - application { - module() - } - addTestData() val pw_hash = DatabaseHandler.getClient("TestClient1")!!.passwordHash @@ -49,10 +46,6 @@ class ApplicationKtTest { } } - application { - module() - } - addTestData() client.post("/protected/exit") { @@ -71,10 +64,6 @@ class ApplicationKtTest { } } - application { - module() - } - addTestData() val pw_hash = DatabaseHandler.getClient("TestClient1")!!.passwordHash @@ -88,10 +77,6 @@ class ApplicationKtTest { @Test fun testPostExitNoBody() = testApplication { - application { - module() - } - client.post("/protected/exit").apply { assertEquals(401, this.status.value) } @@ -99,10 +84,6 @@ class ApplicationKtTest { @Test fun testHeartbeatRequestNoBody() = testApplication { - application { - module() - } - client.post("/protected/heartbeat").apply { assertEquals(401, this.status.value) } @@ -120,10 +101,6 @@ class ApplicationKtTest { val pw_hash = DatabaseHandler.getClient("TestClient1")!!.passwordHash - application { - module() - } - client.post("/protected/heartbeat") { basicAuth("00000000-0000-0000-0000-000000000001", pw_hash) }.apply { @@ -140,10 +117,6 @@ class ApplicationKtTest { } } - application { - module() - } - addTestData() client.post("/protected/heartbeat") { @@ -155,10 +128,6 @@ class ApplicationKtTest { @Test fun testRegisterRequestNoBody() = testApplication { - application { - module() - } - client.post("/register").apply { assertEquals(400, this.status.value) } @@ -172,10 +141,6 @@ class ApplicationKtTest { } } - application { - module() - } - client.post("/register") { contentType(ContentType.Application.Json) setBody( @@ -201,10 +166,6 @@ class ApplicationKtTest { } } - application { - module() - } - client.post("/register") { contentType(ContentType.Application.Json) setBody( @@ -224,9 +185,6 @@ class ApplicationKtTest { @Test fun testSearchRequestNoBody() = testApplication { - application { - module() - } client.get("/protected/search").apply { assertEquals(401, this.status.value) @@ -241,10 +199,6 @@ class ApplicationKtTest { } } - application { - module() - } - addTestData() val pw_hash = DatabaseHandler.getClient("TestClient1")!!.passwordHash diff --git a/server/src/test/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandlerTest.kt b/server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandlerTest.kt similarity index 98% rename from server/src/test/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandlerTest.kt rename to server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandlerTest.kt index facbbd3..7dcc8bd 100644 --- a/server/src/test/kotlin/org/muellerssoftware/openproximitychat/DatabaseHandlerTest.kt +++ b/server/src/test/kotlin/org/muellerssoftware/openproximitychat/tracker/DatabaseHandlerTest.kt @@ -1,4 +1,4 @@ -package org.muellerssoftware.openproximitychat +package org.muellerssoftware.openproximitychat.tracker import org.h2.security.SHA3 import org.junit.Before