mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-03 05:26:50 +01:00
275173e538
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 0c5d8709 SPIGOT-7400: Downgrade maven-resolver due to issues resolving certain depends 255c4fdb SPIGOT-7380: Add PlayerInteractEvent#getClickedPosition and ChiseledBookshelf#getSlot CraftBukkit Changes: b6b514b7e SPIGOT-7400: Downgrade maven-resolver due to issues resolving certain depends fcff84de9 SPIGOT-7399: Revert null check in CraftMetaItem#safelyAdd 44a4b5649 SPIGOT-7380: Add PlayerInteractEvent#getClickedPosition and ChiseledBookshelf#getSlot 676969d01 SPIGOT-7389: Handle setting null items in ChiseledBookshelf Inventory
364 lines
18 KiB
Diff
364 lines
18 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Andrew Steinborn <git@steinborn.me>
|
|
Date: Mon, 26 Jul 2021 02:15:17 -0400
|
|
Subject: [PATCH] Use Velocity compression and cipher natives
|
|
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index e3e6318e0c83ae6f6ff699918ab0faff9f84c63d..5df3ca7173cf27eb01475b6dc2e5aad38cd5a324 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -33,6 +33,11 @@ dependencies {
|
|
runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
|
|
runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
|
|
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
|
+ // Paper start - Use Velocity cipher
|
|
+ implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") {
|
|
+ isTransitive = false
|
|
+ }
|
|
+ // Paper end
|
|
|
|
runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
|
runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
|
|
diff --git a/src/main/java/net/minecraft/network/CipherDecoder.java b/src/main/java/net/minecraft/network/CipherDecoder.java
|
|
index 778beb445eac5769b9e4e07b4d1294c50ae2602b..c712fb8193115e1ab71b5e40fb0ccb9413062b03 100644
|
|
--- a/src/main/java/net/minecraft/network/CipherDecoder.java
|
|
+++ b/src/main/java/net/minecraft/network/CipherDecoder.java
|
|
@@ -7,13 +7,29 @@ import java.util.List;
|
|
import javax.crypto.Cipher;
|
|
|
|
public class CipherDecoder extends MessageToMessageDecoder<ByteBuf> {
|
|
- private final CipherBase cipher;
|
|
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
|
|
|
|
- public CipherDecoder(Cipher cipher) {
|
|
- this.cipher = new CipherBase(cipher);
|
|
+ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
|
|
+ this.cipher = cipher; // Paper
|
|
}
|
|
|
|
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
|
|
- list.add(this.cipher.decipher(channelHandlerContext, byteBuf));
|
|
+ // Paper start
|
|
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
|
|
+ try {
|
|
+ cipher.process(compatible);
|
|
+ list.add(compatible);
|
|
+ } catch (Exception e) {
|
|
+ compatible.release(); // compatible will never be used if we throw an exception
|
|
+ throw e;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
+
|
|
+ // Paper start
|
|
+ @Override
|
|
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
|
+ cipher.close();
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java
|
|
index 0f3d502a9680006bcdcd7d272240a2e5c3b46790..5dd7be70603e8754d2625bb9d16900cb01b9c730 100644
|
|
--- a/src/main/java/net/minecraft/network/CipherEncoder.java
|
|
+++ b/src/main/java/net/minecraft/network/CipherEncoder.java
|
|
@@ -4,15 +4,32 @@ import io.netty.buffer.ByteBuf;
|
|
import io.netty.channel.ChannelHandlerContext;
|
|
import io.netty.handler.codec.MessageToByteEncoder;
|
|
import javax.crypto.Cipher;
|
|
+import java.util.List;
|
|
|
|
-public class CipherEncoder extends MessageToByteEncoder<ByteBuf> {
|
|
- private final CipherBase cipher;
|
|
+public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder<ByteBuf> { // Paper - change superclass
|
|
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
|
|
|
|
- public CipherEncoder(Cipher cipher) {
|
|
- this.cipher = new CipherBase(cipher);
|
|
+ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
|
|
+ this.cipher = cipher; // Paper
|
|
}
|
|
|
|
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception {
|
|
- this.cipher.encipher(byteBuf, byteBuf2);
|
|
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
|
|
+ // Paper start
|
|
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
|
|
+ try {
|
|
+ cipher.process(compatible);
|
|
+ list.add(compatible);
|
|
+ } catch (Exception e) {
|
|
+ compatible.release(); // compatible will never be used if we throw an exception
|
|
+ throw e;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
+
|
|
+ // Paper start
|
|
+ @Override
|
|
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
|
+ cipher.close();
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java
|
|
index b62be99c57b0a5bba0dc29809557d4d247698b13..f4d4ad983baf24d889441541d5a84dc1f49ea4d4 100644
|
|
--- a/src/main/java/net/minecraft/network/CompressionDecoder.java
|
|
+++ b/src/main/java/net/minecraft/network/CompressionDecoder.java
|
|
@@ -12,13 +12,20 @@ public class CompressionDecoder extends ByteToMessageDecoder {
|
|
public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
|
|
public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
|
|
private final Inflater inflater;
|
|
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
|
|
private int threshold;
|
|
private boolean validateDecompressed;
|
|
|
|
+ // Paper start
|
|
public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) {
|
|
+ this(null, compressionThreshold, rejectsBadPackets);
|
|
+ }
|
|
+ public CompressionDecoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean rejectsBadPackets) {
|
|
this.threshold = compressionThreshold;
|
|
this.validateDecompressed = rejectsBadPackets;
|
|
- this.inflater = new Inflater();
|
|
+ this.inflater = compressor == null ? new Inflater() : null;
|
|
+ this.compressor = compressor;
|
|
+ // Paper end
|
|
}
|
|
|
|
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
|
|
@@ -38,6 +45,8 @@ public class CompressionDecoder extends ByteToMessageDecoder {
|
|
}
|
|
}
|
|
|
|
+ // Paper start
|
|
+ if (this.inflater != null) {
|
|
byte[] bs = new byte[friendlyByteBuf.readableBytes()];
|
|
friendlyByteBuf.readBytes(bs);
|
|
this.inflater.setInput(bs);
|
|
@@ -45,10 +54,36 @@ public class CompressionDecoder extends ByteToMessageDecoder {
|
|
this.inflater.inflate(cs);
|
|
list.add(Unpooled.wrappedBuffer(cs));
|
|
this.inflater.reset();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int claimedUncompressedSize = i; // OBFHELPER
|
|
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
|
|
+ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize);
|
|
+ try {
|
|
+ this.compressor.inflate(compatibleIn, uncompressed, claimedUncompressedSize);
|
|
+ list.add(uncompressed);
|
|
+ byteBuf.clear();
|
|
+ } catch (Exception e) {
|
|
+ uncompressed.release();
|
|
+ throw e;
|
|
+ } finally {
|
|
+ compatibleIn.release();
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
}
|
|
}
|
|
|
|
+ // Paper start
|
|
+ @Override
|
|
+ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
|
|
+ if (this.compressor != null) {
|
|
+ this.compressor.close();
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
public void setThreshold(int compressionThreshold, boolean rejectsBadPackets) {
|
|
this.threshold = compressionThreshold;
|
|
this.validateDecompressed = rejectsBadPackets;
|
|
diff --git a/src/main/java/net/minecraft/network/CompressionEncoder.java b/src/main/java/net/minecraft/network/CompressionEncoder.java
|
|
index 792883afe53d2b7989c25a81c2f9a639d5e21d20..c04379ca8a4db0f4de46ad2b3b3384310eebddf3 100644
|
|
--- a/src/main/java/net/minecraft/network/CompressionEncoder.java
|
|
+++ b/src/main/java/net/minecraft/network/CompressionEncoder.java
|
|
@@ -6,22 +6,37 @@ import io.netty.handler.codec.MessageToByteEncoder;
|
|
import java.util.zip.Deflater;
|
|
|
|
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
|
- private final byte[] encodeBuf = new byte[8192];
|
|
+ private final byte[] encodeBuf; // Paper
|
|
private final Deflater deflater;
|
|
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
|
|
private int threshold;
|
|
|
|
+ // Paper start
|
|
public CompressionEncoder(int compressionThreshold) {
|
|
+ this(null, compressionThreshold);
|
|
+ }
|
|
+ public CompressionEncoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold) {
|
|
this.threshold = compressionThreshold;
|
|
- this.deflater = new Deflater();
|
|
+ if (compressor == null) {
|
|
+ this.encodeBuf = new byte[8192];
|
|
+ this.deflater = new Deflater();
|
|
+ } else {
|
|
+ this.encodeBuf = null;
|
|
+ this.deflater = null;
|
|
+ }
|
|
+ this.compressor = compressor;
|
|
+ // Paper end
|
|
}
|
|
|
|
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) {
|
|
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper
|
|
int i = byteBuf.readableBytes();
|
|
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf2);
|
|
if (i < this.threshold) {
|
|
friendlyByteBuf.writeVarInt(0);
|
|
friendlyByteBuf.writeBytes(byteBuf);
|
|
} else {
|
|
+ // Paper start
|
|
+ if (this.deflater != null) {
|
|
byte[] bs = new byte[i];
|
|
byteBuf.readBytes(bs);
|
|
friendlyByteBuf.writeVarInt(bs.length);
|
|
@@ -34,10 +49,48 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
|
}
|
|
|
|
this.deflater.reset();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ friendlyByteBuf.writeVarInt(i);
|
|
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
|
|
+ try {
|
|
+ this.compressor.deflate(compatibleIn, byteBuf2);
|
|
+ } finally {
|
|
+ compatibleIn.release();
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
|
|
}
|
|
|
|
+ // Paper start
|
|
+ @Override
|
|
+ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{
|
|
+ if (this.compressor != null) {
|
|
+ // We allocate bytes to be compressed plus 1 byte. This covers two cases:
|
|
+ //
|
|
+ // - Compression
|
|
+ // According to https://github.com/ebiggers/libdeflate/blob/master/libdeflate.h#L103,
|
|
+ // if the data compresses well (and we do not have some pathological case) then the maximum
|
|
+ // size the compressed size will ever be is the input size minus one.
|
|
+ // - Uncompressed
|
|
+ // This is fairly obvious - we will then have one more than the uncompressed size.
|
|
+ int initialBufferSize = msg.readableBytes() + 1;
|
|
+ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, initialBufferSize);
|
|
+ }
|
|
+
|
|
+ return super.allocateBuffer(ctx, msg, preferDirect);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
|
+ if (this.compressor != null) {
|
|
+ this.compressor.close();
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
public int getThreshold() {
|
|
return this.threshold;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
|
index 5237eb10ca12f786bba66f5db2a2553fa10ffe62..1b634b303105a0f8424e1e40b7c39f9938232d95 100644
|
|
--- a/src/main/java/net/minecraft/network/Connection.java
|
|
+++ b/src/main/java/net/minecraft/network/Connection.java
|
|
@@ -724,11 +724,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
return networkmanager;
|
|
}
|
|
|
|
- public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
|
|
- this.encrypted = true;
|
|
- this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
|
|
- this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
|
|
+ // Paper start
|
|
+// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
|
|
+// this.encrypted = true;
|
|
+// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
|
|
+// this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
|
|
+// }
|
|
+
|
|
+ public void setupEncryption(javax.crypto.SecretKey key) throws net.minecraft.util.CryptException {
|
|
+ if (!this.encrypted) {
|
|
+ try {
|
|
+ com.velocitypowered.natives.encryption.VelocityCipher decryption = com.velocitypowered.natives.util.Natives.cipher.get().forDecryption(key);
|
|
+ com.velocitypowered.natives.encryption.VelocityCipher encryption = com.velocitypowered.natives.util.Natives.cipher.get().forEncryption(key);
|
|
+
|
|
+ this.encrypted = true;
|
|
+ this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryption));
|
|
+ this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryption));
|
|
+ } catch (java.security.GeneralSecurityException e) {
|
|
+ throw new net.minecraft.util.CryptException(e);
|
|
+ }
|
|
+ }
|
|
}
|
|
+ // Paper end
|
|
|
|
public boolean isEncrypted() {
|
|
return this.encrypted;
|
|
@@ -760,16 +777,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
|
|
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
|
|
if (compressionThreshold >= 0) {
|
|
+ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); // Paper
|
|
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
|
|
((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets);
|
|
} else {
|
|
- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
|
|
+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper
|
|
}
|
|
|
|
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
|
|
((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold);
|
|
} else {
|
|
- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
|
|
+ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper
|
|
}
|
|
this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
|
index 838244e3680ea6020701e10bafbde7f52976eaa1..e5e2f763d9b4b955df79ea0c4c79565be1fe59f0 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
|
@@ -103,6 +103,11 @@ public class ServerConnectionListener {
|
|
ServerConnectionListener.LOGGER.info("Using default channel type");
|
|
}
|
|
|
|
+ // Paper start - indicate Velocity natives in use
|
|
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
|
|
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
|
|
+ // Paper end
|
|
+
|
|
this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
|
|
protected void initChannel(Channel channel) {
|
|
try {
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
index b026c003e1fc02a9ea426f3126acb788fc09a874..595779cfd0ee1c405d7936f00a7cae1706125e7f 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
@@ -265,12 +265,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
|
}
|
|
|
|
SecretKey secretkey = packet.getSecretKey(privatekey);
|
|
- Cipher cipher = Crypt.getCipher(2, secretkey);
|
|
- Cipher cipher1 = Crypt.getCipher(1, secretkey);
|
|
+ // Paper start
|
|
+// Cipher cipher = Crypt.getCipher(2, secretkey);
|
|
+// Cipher cipher1 = Crypt.getCipher(1, secretkey);
|
|
+ // Paper end
|
|
|
|
s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16);
|
|
this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING;
|
|
- this.connection.setEncryptionKey(cipher, cipher1);
|
|
+ this.connection.setupEncryption(secretkey); // Paper
|
|
} catch (CryptException cryptographyexception) {
|
|
throw new IllegalStateException("Protocol error", cryptographyexception);
|
|
}
|