Move all tracker code to its own package and switch to Netty Engine instead of embeddedServer
This commit is contained in:
parent
2c5adf86a1
commit
55587fa9a5
|
@ -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<Int, Int>()
|
||||
var discoveryJob: Job = Job()
|
||||
private var gateway: GatewayDevice? = null
|
||||
private val mappedPorts = mutableMapOf<Int, MappedPort>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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<String>): 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<ClientPrincipal>()!!.uuid)
|
||||
|
@ -124,8 +141,4 @@ fun Application.module() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
package org.muellerssoftware.openproximitychat
|
||||
package org.muellerssoftware.openproximitychat.tracker
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
package org.muellerssoftware.openproximitychat
|
||||
package org.muellerssoftware.openproximitychat.tracker
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
|
@ -1,4 +1,4 @@
|
|||
package org.muellerssoftware.openproximitychat
|
||||
package org.muellerssoftware.openproximitychat.tracker
|
||||
|
||||
import io.ktor.server.application.*
|
||||
|
6
server/src/main/resources/application.yaml
Normal file
6
server/src/main/resources/application.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
ktor:
|
||||
deployment:
|
||||
port: 0
|
||||
application:
|
||||
modules:
|
||||
- org.muellerssoftware.openproximitychat.tracker.ApplicationKt.module
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
package org.muellerssoftware.openproximitychat
|
||||
package org.muellerssoftware.openproximitychat.tracker
|
||||
|
||||
import org.h2.security.SHA3
|
||||
import org.junit.Before
|
Loading…
Reference in New Issue
Block a user