From 4de1948ac81194c93c18f98266cbb88fe92121ba Mon Sep 17 00:00:00 2001 From: creeper123123321 <7974274+creeper123123321@users.noreply.github.com> Date: Fri, 25 Jun 2021 20:40:51 -0300 Subject: [PATCH] close #160, close #149 velocity native --- build.gradle.kts | 2 + src/main/kotlin/com/viaversion/aas/VIAaaS.kt | 2 + .../viaversion/aas/codec/CompressionCodec.kt | 92 +++++++++++-------- .../aas/codec/packet/PacketRegistry.kt | 6 +- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5b9fa2c..b0e01c5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,6 +51,7 @@ repositories { maven("https://repo.viaversion.com/") maven("https://repo.aikar.co/content/groups/aikar/") maven("https://jitpack.io") + maven("https://nexus.velocitypowered.com/repository/maven-public/") mavenLocal() } @@ -69,6 +70,7 @@ dependencies { implementation("io.netty:netty-tcnative-boringssl-static:2.0.40.Final") implementation("com.google.guava:guava:30.1.1-jre") + implementation("com.velocitypowered:velocity-native:1.1.0-SNAPSHOT") implementation("org.powernukkit.fastutil:fastutil-lite:8.1.1") implementation("org.yaml:snakeyaml:1.29") diff --git a/src/main/kotlin/com/viaversion/aas/VIAaaS.kt b/src/main/kotlin/com/viaversion/aas/VIAaaS.kt index ee154ea..d0d5de3 100644 --- a/src/main/kotlin/com/viaversion/aas/VIAaaS.kt +++ b/src/main/kotlin/com/viaversion/aas/VIAaaS.kt @@ -1,6 +1,7 @@ package com.viaversion.aas import com.google.gson.JsonParser +import com.velocitypowered.natives.util.Natives import com.viaversion.aas.command.VIAaaSConsole import com.viaversion.aas.command.ViaAspirinCommand import com.viaversion.aas.config.VIAaaSConfig @@ -150,6 +151,7 @@ private fun bindPorts(args: Array) { .childOption(ChannelOption.TCP_NODELAY, true) .bind(InetAddress.getByName(VIAaaSConfig.bindAddress), VIAaaSConfig.port) + viaaasLogger.info("Using compression: ${Natives.compress.loadedVariant}") viaaasLogger.info("Binded minecraft into " + chFuture!!.sync().channel().localAddress()) ktorServer = embeddedServer(Netty, commandLineEnvironment(args)) {}.start(false) } diff --git a/src/main/kotlin/com/viaversion/aas/codec/CompressionCodec.kt b/src/main/kotlin/com/viaversion/aas/codec/CompressionCodec.kt index eb86b00..394ad4d 100644 --- a/src/main/kotlin/com/viaversion/aas/codec/CompressionCodec.kt +++ b/src/main/kotlin/com/viaversion/aas/codec/CompressionCodec.kt @@ -1,72 +1,84 @@ package com.viaversion.aas.codec -import com.viaversion.aas.util.StacklessException +import com.velocitypowered.natives.compression.VelocityCompressor +import com.velocitypowered.natives.util.MoreByteBufUtils +import com.velocitypowered.natives.util.Natives import com.viaversion.viaversion.api.type.Type import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext +import io.netty.handler.codec.DecoderException import io.netty.handler.codec.MessageToMessageCodec -import java.util.zip.Deflater -import java.util.zip.Inflater class CompressionCodec(val threshold: Int) : MessageToMessageCodec() { - // https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java - private val inflater: Inflater = Inflater() - private val deflater: Deflater = Deflater() + // stolen from Krypton (GPL) and modified + // https://github.com/astei/krypton/blob/master/src/main/java/me/steinborn/krypton/mod/shared/network/compression/MinecraftCompressEncoder.java + private val VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 2 * 1024 * 1024 // 2MiB + private val HARD_MAXIMUM_UNCOMPRESSED_SIZE = 16 * 1024 * 1024 // 16MiB + private val UNCOMPRESSED_CAP = + if (java.lang.Boolean.getBoolean("velocity.increased-compression-cap")) HARD_MAXIMUM_UNCOMPRESSED_SIZE else VANILLA_MAXIMUM_UNCOMPRESSED_SIZE + private lateinit var compressor: VelocityCompressor - @Throws(Exception::class) - override fun encode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList) { - val frameLength = input.readableBytes() - val outBuf = ctx.alloc().buffer() + override fun handlerAdded(ctx: ChannelHandlerContext) { + compressor = Natives.compress.get().create(threshold) + } + override fun handlerRemoved(ctx: ChannelHandlerContext) { + compressor.close() + } + + override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList) { + if (!ctx.channel().isActive) return + + val outBuf = allocateBuffer(ctx, msg) try { - if (frameLength < threshold) { + val uncompressedSize = msg.readableBytes() + if (uncompressedSize < threshold) { // Not compressed outBuf.writeByte(0) - outBuf.writeBytes(input) - out.add(outBuf.retain()) - return - } - Type.VAR_INT.writePrimitive(outBuf, frameLength) - deflater.setInput(input.nioBuffer()) - deflater.finish() - while (!deflater.finished()) { - outBuf.ensureWritable(8192) - val wIndex = outBuf.writerIndex() - outBuf.writerIndex(wIndex + deflater.deflate(outBuf.nioBuffer(wIndex, outBuf.writableBytes()))) + outBuf.writeBytes(msg) + } else { + Type.VAR_INT.writePrimitive(outBuf, uncompressedSize) + val compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg) + try { + compressor.deflate(compatibleIn, outBuf) + } finally { + compatibleIn.release() + } } out.add(outBuf.retain()) } finally { outBuf.release() - deflater.reset() } } - @Throws(Exception::class) + private fun allocateBuffer(ctx: ChannelHandlerContext, msg: ByteBuf): ByteBuf { + val initialBufferSize = msg.readableBytes() + 1 + return MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, initialBufferSize) + } + override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList) { if (!input.isReadable || !ctx.channel().isActive) return - val outLength = Type.VAR_INT.readPrimitive(input) - if (outLength == 0) { + + val claimedUncompressedSize = Type.VAR_INT.readPrimitive(input) + if (claimedUncompressedSize == 0) { // Uncompressed out.add(input.retain()) return } - if (outLength < threshold) { - throw StacklessException("Badly compressed packet - size of $outLength is below server threshold of $threshold") + if (claimedUncompressedSize < threshold) { + throw DecoderException("Badly compressed packet - size of $claimedUncompressedSize is below server threshold of $threshold") } - if (outLength > 2097152) { - throw StacklessException("Badly compressed packet - size of $outLength is larger than protocol maximum of 2097152") + if (claimedUncompressedSize > UNCOMPRESSED_CAP) { + throw DecoderException("Badly compressed packet - size of $claimedUncompressedSize is larger than maximum of $UNCOMPRESSED_CAP") } - - inflater.setInput(input.nioBuffer()) - val output = ctx.alloc().buffer(outLength, outLength) + val compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, input) + val decompressed = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize) try { - output.writerIndex( - output.writerIndex() + inflater.inflate(output.nioBuffer(output.writerIndex(), output.writableBytes())) - ) - out.add(output.retain()) + compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize) + input.clear() + out.add(decompressed.retain()) } finally { - inflater.reset() - output.release() + decompressed.release() + compatibleIn.release() } } - } diff --git a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt index 66be414..6eac3c8 100644 --- a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt +++ b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt @@ -57,7 +57,7 @@ object PacketRegistry { ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.DISCONNECT.id, ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.DISCONNECT.id, ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.DISCONNECT.id, - Range.singleton(ProtocolVersion.v1_17.originalVersion) to ClientboundPackets1_17.DISCONNECT.id + ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id ) ) @@ -70,7 +70,7 @@ object PacketRegistry { ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.PLUGIN_MESSAGE.id, ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.PLUGIN_MESSAGE.id, ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.PLUGIN_MESSAGE.id, - Range.singleton(ProtocolVersion.v1_17.originalVersion) to ClientboundPackets1_17.PLUGIN_MESSAGE.id + ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.PLUGIN_MESSAGE.id ) ) } @@ -79,6 +79,8 @@ object PacketRegistry { return Range.closed(this.originalVersion, o.originalVersion) } + val ProtocolVersion.singleton get() = Range.singleton(this.originalVersion) + inline fun register( state: State, direction: Direction,