Compare commits

...

2 Commits

6 changed files with 62 additions and 125 deletions

View File

@ -1,69 +0,0 @@
@file:OptIn(DelicateCoroutinesApi::class)
package org.muellerssoftware.openproximitychat.common
import kotlinx.coroutines.*
import org.bitlet.weupnp.GatewayDevice
import org.bitlet.weupnp.GatewayDiscover
data class MappedPort(val port: Int, val protocol: String)
object UPnPManager {
private var gateway: GatewayDevice? = null
private val mappedPorts = mutableMapOf<Int, MappedPort>()
private var discoveryJob: Job = Job()
init {
runBlocking {
discoveryJob = GlobalScope.launch {
startGatewayDiscover()
}
}
}
fun startGatewayDiscover() {
val gatewayDiscoverer = GatewayDiscover()
for (i in 0..9) {
Logging.info("Searching for UPnP gateway... (Attempt ${i + 1})")
gatewayDiscoverer.discover()
gateway = GatewayDevice()
if (gatewayDiscoverer.validGateway != null) {
gateway = gatewayDiscoverer.validGateway
break
}
}
if (gateway == null) {
Logging.error("No UPnP gateway found!")
}
else {
Logging.info("UPnP gateway found: ${gateway!!.friendlyName}")
val ports = mappedPorts.toMutableMap()
mappedPorts.clear()
ports.map {
mapPort(it.key, it.value.port, it.value.protocol)
}
}
}
fun mapPort(port: Int, protocol: String = "TCP") {
mapPort(port, port, protocol)
}
fun mapPort(internalPort: Int, externalPort: Int, protocol: String = "TCP") {
if (gateway == null) {
mappedPorts[internalPort] = MappedPort(externalPort, protocol)
}
val succeeded = gateway?.addPortMapping(externalPort, internalPort, gateway!!.localAddress.hostAddress, "TCP", "OpenProximityChat mapped port")
if (succeeded == true) {
mappedPorts[internalPort] = MappedPort(externalPort, protocol)
}
}
fun unMapAll() {
mappedPorts.map {
gateway?.deletePortMapping(it.value.port, it.value.protocol)
}
}
}

View File

@ -25,7 +25,6 @@ object VoiceServer {
var handshook = mutableMapOf<UUID, InetAddress>()
init {
UPnPManager.mapPort(localAddress.port)
runBlocking {
startServer()
@ -75,7 +74,6 @@ object VoiceServer {
fun exit() {
Logging.info("VoiceServer exiting...")
UPnPManager.unMapAll()
if (recieverJob.isActive) {
runBlocking {
recieverJob.cancelAndJoin()

View File

@ -1,10 +1,16 @@
@file:UseSerializers(UUIDAsStringSerializer::class, InstantAsStringSerializer::class)
@file:UseSerializers(
org.muellerssoftware.openproximitychat.common.UUIDSerializer::class,
InstantAsStringSerializer::class
)
package org.muellerssoftware.openproximitychat.tracker
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import org.h2.security.SHA3
import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.UUIDEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@ -26,6 +32,46 @@ class Client(
var sampledClients: List<UUID>
)
class ClientEntity(id: EntityID<UUID>): UUIDEntity(id) {
companion object : UUIDEntityClass<ClientEntity>(Clients)
var uuid by Clients.id
var name by Clients.name
var timeout by Clients.timeout
var ip by Clients.ip
var port by Clients.port
var passwordHash by Clients.passwordHash
var sampledClient1 by Clients.sampledClient1
var sampledClient2 by Clients.sampledClient2
var sampledClient3 by Clients.sampledClient3
var sampledClient4 by Clients.sampledClient4
var sampledClient5 by Clients.sampledClient5
var sampledClient6 by Clients.sampledClient6
var sampledClient7 by Clients.sampledClient7
var sampledClient8 by Clients.sampledClient8
fun toClient(): Client {
return Client(
uuid.value,
name,
timeout,
ip,
port,
passwordHash,
listOfNotNull(
sampledClient1,
sampledClient2,
sampledClient3,
sampledClient4,
sampledClient5,
sampledClient6,
sampledClient7,
sampledClient8
)
)
}
}
object Clients: UUIDTable() {
var name = varchar("name", 16)
var ip = varchar("ip", 21)
@ -92,9 +138,9 @@ object DatabaseHandler {
return pw
}
private fun checkTimeout(client: Client): Client? {
private fun checkTimeout(client: ClientEntity): ClientEntity? {
if (client.timeout < Instant.now()) {
removeClient(client.uuid)
client.delete()
return null
}
@ -102,29 +148,15 @@ object DatabaseHandler {
}
fun getClient(name: String): Client? {
val client = transaction {
Clients.select { Clients.name eq name }.map {
Client(it[Clients.id].value, it[Clients.name], it[Clients.timeout], it[Clients.ip], it[Clients.port], it[Clients.passwordHash], listOf(
it[Clients.sampledClient1],it[Clients.sampledClient2],it[Clients.sampledClient3],it[Clients.sampledClient4],
it[Clients.sampledClient5],it[Clients.sampledClient6],it[Clients.sampledClient7],it[Clients.sampledClient8]
))
}.firstOrNull()
} ?: return null
return checkTimeout(client)
return transaction {
ClientEntity.find { Clients.name eq name }.firstOrNull()
}?.let { checkTimeout(it) }?.toClient()
}
fun getClient(id: UUID): Client? {
val client = transaction {
Clients.select { Clients.id eq id }.map {
Client(it[Clients.id].value, it[Clients.name], it[Clients.timeout], it[Clients.ip], it[Clients.port], it[Clients.passwordHash], listOf(
it[Clients.sampledClient1],it[Clients.sampledClient2],it[Clients.sampledClient3],it[Clients.sampledClient4],
it[Clients.sampledClient5],it[Clients.sampledClient6],it[Clients.sampledClient7],it[Clients.sampledClient8]
))
}.firstOrNull()
} ?: return null
return checkTimeout(client)
return transaction {
ClientEntity.find { Clients.id eq id }.firstOrNull()
}?.let { checkTimeout(it) }?.toClient()
}
fun doHeartbeat(id: UUID): String {
@ -148,9 +180,11 @@ object DatabaseHandler {
}
fun checkCredentials(id: UUID, passwordHash: String): Boolean {
val client = getClient(id) ?: return false
val client = transaction {
ClientEntity.find { Clients.id eq id }.firstOrNull()
}?.let { checkTimeout(it) }
return if (checkTimeout(client) != null) {
return if (client != null) {
client.passwordHash == passwordHash
} else {
false

View File

@ -6,6 +6,7 @@ import io.ktor.server.application.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.select
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import org.muellerssoftware.openproximitychat.common.Logging
@ -35,7 +36,7 @@ fun Application.puncher() {
}
transaction {
Clients.update({ Clients.id eq uuid }) {
Clients.update({ Clients.id eq uuid and (Clients.port eq null) }) {
it[ip] = address.toJavaAddress().toString()
}.run {
if (this == 0) {

View File

@ -1,4 +1,4 @@
@file:UseSerializers(UUIDAsStringSerializer::class)
@file:UseSerializers(org.muellerssoftware.openproximitychat.common.UUIDSerializer::class)
package org.muellerssoftware.openproximitychat.tracker

View File

@ -1,27 +0,0 @@
package org.muellerssoftware.openproximitychat.tracker
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.util.*
@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = UUID::class)
object UUIDAsStringSerializer: KSerializer<UUID> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUIDAsStringSerializer", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: UUID) {
val string = value.toString()
encoder.encodeString(string)
}
override fun deserialize(decoder: Decoder): UUID {
val string = decoder.decodeString()
return UUID.fromString(string)
}
}