mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2024-09-30 04:57:50 +02:00
better algorithm for lilypad workaround, update deps
test if native compressor works before using it
This commit is contained in:
parent
5fac0e2ae2
commit
9757e76cd6
@ -68,7 +68,7 @@ dependencies {
|
||||
implementation("com.github.ViaVersion.ViaRewind:viarewind-all:$vrVer") { isTransitive = false }
|
||||
|
||||
implementation("io.netty:netty-all:4.1.67.Final")
|
||||
implementation("io.netty:netty-tcnative-boringssl-static:2.0.40.Final")
|
||||
implementation("io.netty:netty-tcnative-boringssl-static:2.0.41.Final")
|
||||
implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.8.Final:linux-x86_64")
|
||||
|
||||
implementation("com.google.guava:guava:30.1.1-jre")
|
||||
@ -142,7 +142,7 @@ tasks.named<ProcessResources>("processResources") {
|
||||
)
|
||||
}
|
||||
filesMatching("**/*.js") {
|
||||
//filter<JsMinifyFilter>()
|
||||
filter<JsMinifyFilter>()
|
||||
}
|
||||
filesMatching("**/*.html") {
|
||||
filter<HtmlMinifyFilter>()
|
||||
|
@ -1,8 +1,5 @@
|
||||
package com.viaversion.aas.codec;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.velocitypowered.natives.compression.JavaVelocityCompressor;
|
||||
import com.velocitypowered.natives.compression.VelocityCompressor;
|
||||
import com.velocitypowered.natives.util.MoreByteBufUtils;
|
||||
@ -11,28 +8,21 @@ import com.viaversion.aas.config.VIAaaSConfig;
|
||||
import com.viaversion.aas.handler.MinecraftHandler;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.MessageToMessageCodec;
|
||||
import kotlin.Pair;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.DataFormatException;
|
||||
|
||||
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 UNCOMPRESSED_CAP = 8 * 1024 * 1024; // 8MiB
|
||||
// Workaround for Lilypad backend servers
|
||||
private static final LoadingCache<SocketAddress, Pair<AtomicInteger, AtomicInteger>> nativeFails = CacheBuilder
|
||||
.newBuilder()
|
||||
.expireAfterWrite(2, TimeUnit.HOURS)
|
||||
.build(CacheLoader.from(() -> new Pair<>(new AtomicInteger(), new AtomicInteger())));
|
||||
private int threshold;
|
||||
private VelocityCompressor compressor;
|
||||
private VelocityCompressor testingCompressor;
|
||||
|
||||
public CompressionCodec(int threshold) {
|
||||
this.threshold = threshold;
|
||||
@ -44,29 +34,39 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
var useNative = true;
|
||||
|
||||
var attempts = getAttempts(ctx);
|
||||
if (attempts != null && Math.random() <= 0.95) {
|
||||
// We'll use Java when the native compression fail rate is high
|
||||
var probabilityNo = attempts.getSecond().get() + 1;
|
||||
var divisor = attempts.getFirst().get() + 2;
|
||||
useNative = !(Math.random() <= (double) probabilityNo / divisor);
|
||||
}
|
||||
|
||||
var level = VIAaaSConfig.INSTANCE.getCompressionLevel();
|
||||
if (useNative) {
|
||||
compressor = Natives.compress.get().create(level);
|
||||
} else {
|
||||
|
||||
var cNative = Natives.compress.get().create(level);
|
||||
if (isBackend(ctx) && !Natives.compress.getLoadedVariant().equalsIgnoreCase("java")) {
|
||||
// Workaround for Lilypad backend servers
|
||||
compressor = JavaVelocityCompressor.FACTORY.create(level);
|
||||
testingCompressor = cNative;
|
||||
} else {
|
||||
compressor = cNative;
|
||||
}
|
||||
}
|
||||
|
||||
recordHandlerAdded(ctx);
|
||||
private boolean isBackend(ChannelHandlerContext ctx) {
|
||||
var handler = ctx.pipeline().get(MinecraftHandler.class);
|
||||
return handler != null && !handler.getFrontEnd();
|
||||
}
|
||||
|
||||
private void useTestCompressor() {
|
||||
compressor.close();
|
||||
compressor = testingCompressor;
|
||||
testingCompressor = null;
|
||||
}
|
||||
|
||||
private void discardTestCompressor() {
|
||||
if (testingCompressor == null) return;
|
||||
testingCompressor.close();
|
||||
testingCompressor = null; // Discard it, compressor doesn't know how to decompress this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerRemoved(ChannelHandlerContext ctx) {
|
||||
compressor.close();
|
||||
discardTestCompressor();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,32 +99,6 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
|
||||
return MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, initialBufferSize);
|
||||
}
|
||||
|
||||
private Pair<AtomicInteger, AtomicInteger> getAttempts(ChannelHandlerContext ctx) {
|
||||
var handler = ctx.pipeline().get(MinecraftHandler.class);
|
||||
if (handler == null || handler.getFrontEnd() || !ctx.channel().isActive()) return null;
|
||||
var addr = handler.getEndRemoteAddress();
|
||||
|
||||
return nativeFails.getUnchecked(addr);
|
||||
}
|
||||
|
||||
private void recordHandlerAdded(ChannelHandlerContext ctx) {
|
||||
if (compressor instanceof JavaVelocityCompressor) return; // Only record errors happened with native
|
||||
|
||||
var attempts = getAttempts(ctx);
|
||||
if (attempts != null) {
|
||||
attempts.getFirst().incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
private void recordDecompressFailed(ChannelHandlerContext ctx) {
|
||||
if (compressor instanceof JavaVelocityCompressor) return; // Only record errors happened with native
|
||||
|
||||
var attempts = getAttempts(ctx);
|
||||
if (attempts != null) {
|
||||
attempts.getSecond().incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
|
||||
if (!input.isReadable() || !ctx.channel().isActive()) return;
|
||||
@ -143,19 +117,42 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
|
||||
}
|
||||
var compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, input);
|
||||
var decompressed = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
|
||||
try {
|
||||
var readerI = compatibleIn.readerIndex();
|
||||
try {
|
||||
compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize);
|
||||
input.clear();
|
||||
out.add(decompressed.retain());
|
||||
} catch (DataFormatException ex) {
|
||||
if (ex.getMessage().startsWith("Received a deflate stream that was too large, wanted ")) {
|
||||
return; // workaround for lilypad
|
||||
}
|
||||
recordDecompressFailed(ctx);
|
||||
// workaround for lilypad
|
||||
if (!ex.getMessage().startsWith("Received a deflate stream that was too large, wanted ")) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
out.add(decompressed.retain());
|
||||
|
||||
if (testingCompressor != null) {
|
||||
compatibleIn.readerIndex(readerI);
|
||||
testCompressor(compatibleIn, claimedUncompressedSize);
|
||||
}
|
||||
|
||||
input.clear();
|
||||
} finally {
|
||||
decompressed.release();
|
||||
compatibleIn.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void testCompressor(ByteBuf in, int claimedUncompressedSize) {
|
||||
var testOut = ByteBufAllocator.DEFAULT.buffer();
|
||||
try {
|
||||
testingCompressor.inflate(in, testOut, claimedUncompressedSize);
|
||||
|
||||
if (Math.random() <= 0.001) { // Runs more tests
|
||||
useTestCompressor();
|
||||
}
|
||||
} catch (DataFormatException eTest) {
|
||||
discardTestCompressor();
|
||||
} finally {
|
||||
testOut.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user