update ktor, migrated some code to java

This commit is contained in:
creeper123123321 2021-06-30 21:23:39 -03:00
parent 24198352bc
commit e3a5fb3ac0
23 changed files with 363 additions and 265 deletions

View File

@ -84,7 +84,7 @@ dependencies {
implementation("org.jline:jline-terminal-jansi:3.20.0")
implementation("org.slf4j:slf4j-api:$slf4jVer")
val ktorVersion = "1.6.0"
val ktorVersion = "1.6.1"
implementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
implementation("io.ktor:ktor-websockets:$ktorVersion")
implementation("io.ktor:ktor-server-netty:$ktorVersion")

View File

@ -0,0 +1,94 @@
package com.viaversion.aas.codec;
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.List;
public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
// 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 static final int VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 2 * 1024 * 1024; // 2MiB
private static final int HARD_MAXIMUM_UNCOMPRESSED_SIZE = 16 * 1024 * 1024; // 16MiB
private static final int UNCOMPRESSED_CAP = java.lang.Boolean.getBoolean("velocity.increased-compression-cap") ? HARD_MAXIMUM_UNCOMPRESSED_SIZE : VANILLA_MAXIMUM_UNCOMPRESSED_SIZE;
private final int threshold;
private VelocityCompressor compressor;
public CompressionCodec(int threshold) {
this.threshold = threshold;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
compressor = Natives.compress.get().create(6);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
compressor.close();
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
if (!ctx.channel().isActive()) return;
var outBuf = allocateBuffer(ctx, msg);
try {
var uncompressedSize = msg.readableBytes();
if (uncompressedSize < threshold) { // Not compressed
outBuf.writeByte(0);
outBuf.writeBytes(msg);
} else {
Type.VAR_INT.writePrimitive(outBuf, uncompressedSize);
var compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
try {
compressor.deflate(compatibleIn, outBuf);
} finally {
compatibleIn.release();
}
}
out.add(outBuf.retain());
} finally {
outBuf.release();
}
}
private ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg) {
var initialBufferSize = msg.readableBytes() + 1;
return MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, initialBufferSize);
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
if (!input.isReadable() || !ctx.channel().isActive()) return;
var claimedUncompressedSize = Type.VAR_INT.readPrimitive(input);
if (claimedUncompressedSize == 0) { // Uncompressed
out.add(input.retain());
return;
}
if (claimedUncompressedSize < threshold) {
throw new DecoderException("Badly compressed packet - size of $claimedUncompressedSize is below server threshold of $threshold");
}
if (claimedUncompressedSize > UNCOMPRESSED_CAP) {
throw new DecoderException("Badly compressed packet - size of $claimedUncompressedSize is larger than maximum of $UNCOMPRESSED_CAP");
}
var compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, input);
var decompressed = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
try {
compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize);
input.clear();
out.add(decompressed.retain());
} finally {
decompressed.release();
compatibleIn.release();
}
}
}

View File

@ -0,0 +1,36 @@
package com.viaversion.aas.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import org.jetbrains.annotations.NotNull;
import javax.crypto.Cipher;
import java.util.List;
public class CryptoCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
private final Cipher cipherEncode;
private final Cipher cipherDecode;
public CryptoCodec(@NotNull Cipher cipherEncode, @NotNull Cipher cipherDecode) {
this.cipherEncode = cipherEncode;
this.cipherDecode = cipherDecode;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
var i = msg.readerIndex();
var size = msg.readableBytes();
msg.writerIndex(i + cipherEncode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherEncode.getOutputSize(size))));
out.add(msg.retain());
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
if (!ctx.channel().isActive()) return;
var i = msg.readerIndex();
var size = msg.readableBytes();
msg.writerIndex(i + cipherDecode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherDecode.getOutputSize(size))));
out.add(msg.retain());
}
}

View File

@ -0,0 +1,57 @@
package com.viaversion.aas.codec;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.aas.codec.packet.PacketRegistry;
import com.viaversion.aas.handler.MinecraftHandler;
import com.viaversion.aas.util.StacklessException;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.exception.CancelEncoderException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, Packet> {
@Override
protected void encode(@NotNull ChannelHandlerContext ctx, @NotNull Packet msg, @NotNull List<Object> out) {
if (!ctx.channel().isActive()) throw CancelEncoderException.generate(null);
var buf = ByteBufAllocator.DEFAULT.buffer();
try {
var handler = ctx.pipeline().get(MinecraftHandler.class);
PacketRegistry.INSTANCE.encode(
msg,
buf,
handler.getData().getFrontVer(),
handler.getFrontEnd() ? Direction.CLIENTBOUND : Direction.SERVERBOUND
);
out.add(buf.retain());
} finally {
buf.release();
}
}
@Override
protected void decode(@NotNull ChannelHandlerContext ctx, @NotNull ByteBuf msg, @NotNull List<Object> out) {
if (!ctx.channel().isActive() || !msg.isReadable()) return;
var handler = ctx.pipeline().get(MinecraftHandler.class);
var frontVer = handler.getData().getFrontVer();
if (frontVer == null) {
frontVer = 0;
}
out.add(PacketRegistry.INSTANCE.decode(
msg,
frontVer,
handler.getData().getState().getState(),
handler.getFrontEnd() ? Direction.SERVERBOUND : Direction.CLIENTBOUND
));
if (msg.isReadable()) {
throw new StacklessException("Remaining bytes!!!");
}
}
}

View File

@ -0,0 +1,13 @@
package com.viaversion.aas.codec.packet;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
/**
* A mutable object which represents a Minecraft packet data
*/
public interface Packet {
void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception;
void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception;
}

View File

@ -0,0 +1,28 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class LoginDisconnect implements Packet {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
msg = Type.STRING.read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.STRING.write(byteBuf, msg);
}
}

View File

@ -0,0 +1,29 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.StringType;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class LoginStart implements Packet {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
username = new StringType(16).read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.STRING.write(byteBuf, username);
}
}

View File

@ -0,0 +1,28 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class SetCompression implements Packet {
private int threshold;
public int getThreshold() {
return threshold;
}
public void setThreshold(int threshold) {
this.threshold = threshold;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
threshold = Type.VAR_INT.readPrimitive(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.VAR_INT.writePrimitive(byteBuf, threshold);
}
}

View File

@ -0,0 +1,28 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class Kick implements Packet {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
msg = Type.STRING.read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.STRING.write(byteBuf, msg);
}
}

View File

@ -0,0 +1,27 @@
package com.viaversion.aas.codec.packet.status;
import com.viaversion.aas.codec.packet.Packet;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class StatusPing implements Packet {
private long number;
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
number = byteBuf.readLong();
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
byteBuf.writeLong(number);
}
}

View File

@ -0,0 +1,15 @@
package com.viaversion.aas.codec.packet.status;
import com.viaversion.aas.codec.packet.Packet;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class StatusRequest implements Packet {
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
}
}

View File

@ -1,84 +0,0 @@
package com.viaversion.aas.codec
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
class CompressionCodec(val threshold: Int) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
// 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
override fun handlerAdded(ctx: ChannelHandlerContext) {
compressor = Natives.compress.get().create(6)
}
override fun handlerRemoved(ctx: ChannelHandlerContext) {
compressor.close()
}
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
if (!ctx.channel().isActive) return
val outBuf = allocateBuffer(ctx, msg)
try {
val uncompressedSize = msg.readableBytes()
if (uncompressedSize < threshold) { // Not compressed
outBuf.writeByte(0)
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()
}
}
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<Any>) {
if (!input.isReadable || !ctx.channel().isActive) return
val claimedUncompressedSize = Type.VAR_INT.readPrimitive(input)
if (claimedUncompressedSize == 0) { // Uncompressed
out.add(input.retain())
return
}
if (claimedUncompressedSize < threshold) {
throw DecoderException("Badly compressed packet - size of $claimedUncompressedSize is below server threshold of $threshold")
}
if (claimedUncompressedSize > UNCOMPRESSED_CAP) {
throw DecoderException("Badly compressed packet - size of $claimedUncompressedSize is larger than maximum of $UNCOMPRESSED_CAP")
}
val compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, input)
val decompressed = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize)
try {
compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize)
input.clear()
out.add(decompressed.retain())
} finally {
decompressed.release()
compatibleIn.release()
}
}
}

View File

@ -1,23 +0,0 @@
package com.viaversion.aas.codec
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.MessageToMessageCodec
import javax.crypto.Cipher
class CryptoCodec(val cipherDecode: Cipher, var cipherEncode: Cipher) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
if (!ctx.channel().isActive) return
val i = msg.readerIndex()
val size = msg.readableBytes()
msg.writerIndex(i + cipherDecode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherDecode.getOutputSize(size))))
out.add(msg.retain())
}
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
val i = msg.readerIndex()
val size = msg.readableBytes()
msg.writerIndex(i + cipherEncode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherEncode.getOutputSize(size))))
out.add(msg.retain())
}
}

View File

@ -1,45 +0,0 @@
package com.viaversion.aas.codec
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.codec.packet.PacketRegistry
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.Direction
import com.viaversion.viaversion.exception.CancelEncoderException
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.MessageToMessageCodec
class MinecraftCodec : MessageToMessageCodec<ByteBuf, Packet>() {
override fun encode(ctx: ChannelHandlerContext, msg: Packet, out: MutableList<Any>) {
if (!ctx.channel().isActive) throw CancelEncoderException.CACHED
val buf = ByteBufAllocator.DEFAULT.buffer()
try {
val handler = ctx.pipeline().get(MinecraftHandler::class.java)
PacketRegistry.encode(
msg,
buf,
handler.data.frontVer!!,
if (handler.frontEnd) Direction.CLIENTBOUND else Direction.SERVERBOUND
)
out.add(buf.retain())
} finally {
buf.release()
}
}
override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
if (!ctx.channel().isActive || !msg.isReadable) return
val handler = ctx.pipeline().get(MinecraftHandler::class.java)
out.add(
PacketRegistry.decode(
msg,
handler.data.frontVer ?: 0,
handler.data.state.state,
if (handler.frontEnd) Direction.SERVERBOUND else Direction.CLIENTBOUND
)
)
if (msg.isReadable) throw StacklessException("Remaining bytes!!!")
}
}

View File

@ -1,11 +0,0 @@
package com.viaversion.aas.codec.packet
import io.netty.buffer.ByteBuf
/**
* A mutable object which represents a Minecraft packet data
*/
interface Packet {
fun decode(byteBuf: ByteBuf, protocolVersion: Int)
fun encode(byteBuf: ByteBuf, protocolVersion: Int)
}

View File

@ -9,7 +9,6 @@ import com.viaversion.aas.codec.packet.status.StatusPing
import com.viaversion.aas.codec.packet.status.StatusPong
import com.viaversion.aas.codec.packet.status.StatusRequest
import com.viaversion.aas.codec.packet.status.StatusResponse
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.Direction
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion

View File

@ -1,16 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
class LoginDisconnect : Packet {
lateinit var msg: String
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
msg = Type.STRING.read(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, msg)
}
}

View File

@ -1,18 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.types.StringType
import io.netty.buffer.ByteBuf
class LoginStart : Packet {
lateinit var username: String
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
username = StringType(16).read(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, username)
}
}

View File

@ -1,17 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
import kotlin.properties.Delegates
class SetCompression : Packet {
var threshold by Delegates.notNull<Int>()
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
threshold = Type.VAR_INT.readPrimitive(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.VAR_INT.writePrimitive(byteBuf, threshold)
}
}

View File

@ -1,16 +0,0 @@
package com.viaversion.aas.codec.packet.play
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
class Kick : Packet {
lateinit var msg: String
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
msg = Type.STRING.read(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, msg)
}
}

View File

@ -1,16 +0,0 @@
package com.viaversion.aas.codec.packet.status
import com.viaversion.aas.codec.packet.Packet
import io.netty.buffer.ByteBuf
import kotlin.properties.Delegates
class StatusPing : Packet {
var number by Delegates.notNull<Long>()
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
number = byteBuf.readLong()
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
byteBuf.writeLong(number)
}
}

View File

@ -1,12 +0,0 @@
package com.viaversion.aas.codec.packet.status
import com.viaversion.aas.codec.packet.Packet
import io.netty.buffer.ByteBuf
class StatusRequest : Packet {
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
}
}

View File

@ -58,20 +58,22 @@ class LoginState : MinecraftConnectionState {
private fun handleCompression(handler: MinecraftHandler, setCompression: SetCompression) {
val pipe = handler.data.frontChannel.pipeline()
val threshold = setCompression.threshold
val backPipe = pipe.get(MinecraftHandler::class.java).other!!.pipeline()
if (backPipe.get("compress") != null) {
backPipe.remove("compress")
}
if (threshold != -1) {
backPipe.addAfter("frame", "compress", CompressionCodec(threshold))
} else if (backPipe.get("compress") != null) {
backPipe.remove("compress")
}
forward(handler, setCompression)
if (pipe.get("compress") != null) {
pipe.remove("compress")
}
if (threshold != -1) {
pipe.addAfter("frame", "compress", CompressionCodec(threshold))
} else if (pipe.get("compress") != null) {
pipe.remove("compress")
}
}