Start work on UDP Networking + UPnP

This commit is contained in:
Kai 2022-11-06 21:03:50 +00:00
parent c527062515
commit 0d67563f42
11 changed files with 192 additions and 1 deletions

View File

@ -1,5 +1,6 @@
plugins {
kotlin("jvm")
kotlin("plugin.serialization") version "1.7.10"
id("fabric-loom")
`maven-publish`
java
@ -23,6 +24,19 @@ dependencies {
modImplementation("net.fabricmc:fabric-language-kotlin:${property("fabric_kotlin_version")}")
modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}")
// KTOR
implementation("io.ktor:ktor-server-core-jvm:2.1.3")
implementation("io.ktor:ktor-server-netty-jvm:2.1.3")
implementation("io.ktor:ktor-network:2.1.3")
implementation("io.ktor:ktor-network-tls:2.1.3")
// UPnP
implementation("org.bitlet:weupnp:0.1.4")
// Serialization
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.1")
}
tasks {

View File

@ -1,4 +1,10 @@
package org.muellerssoftware.openproximitychatfabric.voice
public class Connection {
import java.util.*
class Connection(val ip: String, val uuid: UUID) {
val targetIP = ip;
val playerUUID = uuid;
}

View File

@ -0,0 +1,32 @@
package org.muellerssoftware.openproximitychatfabric.voice
import org.bitlet.weupnp.GatewayDevice
import org.bitlet.weupnp.GatewayDiscover
object UPnPManager {
val gateway: GatewayDevice
val mappedPorts = mutableMapOf<Int, Int>()
init {
val gatewayDiscoverer = GatewayDiscover()
gatewayDiscoverer.discover()
gateway = gatewayDiscoverer.validGateway;
}
public fun mapPort(port: Int) {
mapPort(port, port)
}
public fun mapPort(internalPort: Int, externalPort: Int) {
val succeeded = gateway.addPortMapping(externalPort, internalPort, gateway.localAddress.hostAddress, "UDP", "OPCFabric mapped port")
if (succeeded) {
mappedPorts.put(internalPort, externalPort)
}
}
public fun unMapAll() {
mappedPorts.map {
gateway.deletePortMapping(it.value, "UDP")
}
}
}

View File

@ -0,0 +1,77 @@
package org.muellerssoftware.openproximitychatfabric.voice
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.util.Identity.decode
import io.ktor.util.Identity.encode
import io.ktor.util.network.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.select
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import org.bitlet.weupnp.GatewayDiscover
import org.muellerssoftware.openproximitychatfabric.OPCFabric
import org.muellerssoftware.openproximitychatfabric.voice.packets.Packet
import org.muellerssoftware.openproximitychatfabric.voice.packets.PacketType
import java.util.UUID
object VoiceServer {
val selector = SelectorManager(Dispatchers.IO)
val socket = aSocket(selector).udp().bind()
val localAddress = socket.localAddress.toJavaAddress()
var recieverJob: Job
var handshook = mutableMapOf<UUID, InetSocketAddress>()
init {
UPnPManager.mapPort(localAddress.port)
runBlocking {
recieverJob = launch {
server()
}
}
}
public suspend fun server() {
try {
select<Unit> {
socket.incoming.onReceive {
val packet = it.decode()
when(packet.type) {
PacketType.Initial -> TODO()
PacketType.Voice -> TODO()
PacketType.Close -> TODO()
}
}
}
}
catch(e: CancellationException) {
OPCFabric.LOGGER.info("VoiceServer exiting...")
}
finally {
socket.close()
}
}
public fun exit() {
if (recieverJob.isActive) {
runBlocking {
recieverJob.cancelAndJoin()
}
}
}
}
@OptIn(ExperimentalSerializationApi::class)
private fun Datagram.decode(): Packet {
return ProtoBuf.decodeFromByteArray(this.packet.readByteBuffer().array())
}
@OptIn(ExperimentalSerializationApi::class)
private fun Packet.encode(): ByteArray {
return ProtoBuf.encodeToByteArray(this)
}

View File

@ -0,0 +1,7 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets.C2S
import kotlinx.serialization.Serializable
@Serializable
class C2SPacket<T>(var packetType: C2SPacketType, var packet: T) {
}

View File

@ -0,0 +1,10 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets.C2S
import kotlinx.serialization.Serializable
@Serializable
enum class C2SPacketType {
Initial,
Voice,
Close
}

View File

@ -0,0 +1,11 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets.C2S
import kotlinx.serialization.Serializable
import org.muellerssoftware.openproximitychatfabric.voice.packets.Packet
import org.muellerssoftware.openproximitychatfabric.voice.packets.PacketType
import java.util.UUID
@Serializable
class ClosePacket {
}

View File

@ -0,0 +1,9 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets.C2S
import kotlinx.serialization.Serializable
import org.muellerssoftware.openproximitychatfabric.voice.packets.Packet
import org.muellerssoftware.openproximitychatfabric.voice.packets.PacketType
@Serializable
class InitialPacket {
}

View File

@ -0,0 +1,9 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets.C2S
import kotlinx.serialization.Serializable
import org.muellerssoftware.openproximitychatfabric.voice.packets.Packet
import org.muellerssoftware.openproximitychatfabric.voice.packets.PacketType
@Serializable
class VoicePacket {
}

View File

@ -0,0 +1,6 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets
import kotlinx.serialization.Serializable
@Serializable
sealed class Packet(val type: PacketType) {}

View File

@ -0,0 +1,10 @@
package org.muellerssoftware.openproximitychatfabric.voice.packets
import kotlinx.serialization.Serializable
@Serializable
enum class PacketType {
Initial,
Voice,
Close
}