Compare commits
2 Commits
20b3b43394
...
3fc97ff6ea
Author | SHA1 | Date | |
---|---|---|---|
3fc97ff6ea | |||
3c999daebc |
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,7 +25,6 @@ object VoiceServer {
|
|||||||
var handshook = mutableMapOf<UUID, InetAddress>()
|
var handshook = mutableMapOf<UUID, InetAddress>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
UPnPManager.mapPort(localAddress.port)
|
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
startServer()
|
startServer()
|
||||||
@ -75,7 +74,6 @@ object VoiceServer {
|
|||||||
|
|
||||||
fun exit() {
|
fun exit() {
|
||||||
Logging.info("VoiceServer exiting...")
|
Logging.info("VoiceServer exiting...")
|
||||||
UPnPManager.unMapAll()
|
|
||||||
if (recieverJob.isActive) {
|
if (recieverJob.isActive) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
recieverJob.cancelAndJoin()
|
recieverJob.cancelAndJoin()
|
||||||
|
@ -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
|
package org.muellerssoftware.openproximitychat.tracker
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
import org.h2.security.SHA3
|
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.dao.id.UUIDTable
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
@ -26,6 +32,46 @@ class Client(
|
|||||||
var sampledClients: List<UUID>
|
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() {
|
object Clients: UUIDTable() {
|
||||||
var name = varchar("name", 16)
|
var name = varchar("name", 16)
|
||||||
var ip = varchar("ip", 21)
|
var ip = varchar("ip", 21)
|
||||||
@ -92,9 +138,9 @@ object DatabaseHandler {
|
|||||||
return pw
|
return pw
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkTimeout(client: Client): Client? {
|
private fun checkTimeout(client: ClientEntity): ClientEntity? {
|
||||||
if (client.timeout < Instant.now()) {
|
if (client.timeout < Instant.now()) {
|
||||||
removeClient(client.uuid)
|
client.delete()
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,29 +148,15 @@ object DatabaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getClient(name: String): Client? {
|
fun getClient(name: String): Client? {
|
||||||
val client = transaction {
|
return transaction {
|
||||||
Clients.select { Clients.name eq name }.map {
|
ClientEntity.find { Clients.name eq name }.firstOrNull()
|
||||||
Client(it[Clients.id].value, it[Clients.name], it[Clients.timeout], it[Clients.ip], it[Clients.port], it[Clients.passwordHash], listOf(
|
}?.let { checkTimeout(it) }?.toClient()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getClient(id: UUID): Client? {
|
fun getClient(id: UUID): Client? {
|
||||||
val client = transaction {
|
return transaction {
|
||||||
Clients.select { Clients.id eq id }.map {
|
ClientEntity.find { Clients.id eq id }.firstOrNull()
|
||||||
Client(it[Clients.id].value, it[Clients.name], it[Clients.timeout], it[Clients.ip], it[Clients.port], it[Clients.passwordHash], listOf(
|
}?.let { checkTimeout(it) }?.toClient()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doHeartbeat(id: UUID): String {
|
fun doHeartbeat(id: UUID): String {
|
||||||
@ -148,9 +180,11 @@ object DatabaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkCredentials(id: UUID, passwordHash: String): Boolean {
|
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
|
client.passwordHash == passwordHash
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -6,6 +6,7 @@ import io.ktor.server.application.*
|
|||||||
import io.ktor.utils.io.core.*
|
import io.ktor.utils.io.core.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import org.jetbrains.exposed.sql.update
|
import org.jetbrains.exposed.sql.update
|
||||||
import org.muellerssoftware.openproximitychat.common.Logging
|
import org.muellerssoftware.openproximitychat.common.Logging
|
||||||
@ -35,7 +36,7 @@ fun Application.puncher() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transaction {
|
transaction {
|
||||||
Clients.update({ Clients.id eq uuid }) {
|
Clients.update({ Clients.id eq uuid and (Clients.port eq null) }) {
|
||||||
it[ip] = address.toJavaAddress().toString()
|
it[ip] = address.toJavaAddress().toString()
|
||||||
}.run {
|
}.run {
|
||||||
if (this == 0) {
|
if (this == 0) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@file:UseSerializers(UUIDAsStringSerializer::class)
|
@file:UseSerializers(org.muellerssoftware.openproximitychat.common.UUIDSerializer::class)
|
||||||
|
|
||||||
package org.muellerssoftware.openproximitychat.tracker
|
package org.muellerssoftware.openproximitychat.tracker
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user