testserver/patches/server/0287-Handle-Large-Packets-d...

116 lines
5.5 KiB
Diff
Raw Normal View History

2021-06-11 12:02:28 +00:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 27 Nov 2018 21:18:06 -0500
Subject: [PATCH] Handle Large Packets disconnecting client
If a players inventory is too big to send in a single packet,
split the inventory set into multiple packets instead.
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 08:02:51 +00:00
index 7d85817a0a041c2fa257396d1508488bfc7da55b..870badca869aca1ad293542b345a038ddf715135 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 08:02:51 +00:00
@@ -148,6 +148,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
2021-06-11 12:02:28 +00:00
}
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
+ // Paper start
2021-06-13 08:26:58 +00:00
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) {
2021-06-11 12:02:28 +00:00
+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) {
+ return;
+ } else {
+ throwable = throwable.getCause();
+ }
+ }
+ // Paper end
if (throwable instanceof SkipPacketException) {
Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
} else {
diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java
2022-03-01 05:43:03 +00:00
index 00d432bd395e7f7fb6ee24e371818d13892b2f0c..5fce1177e7198d791d4ab1c64b394c5b1c145782 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
2022-03-01 05:43:03 +00:00
@@ -54,7 +54,31 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
2021-11-24 00:20:31 +00:00
throw var10;
2021-06-11 12:02:28 +00:00
}
}
+
+ // Paper start
2021-06-13 08:26:58 +00:00
+ int packetLength = friendlyByteBuf.readableBytes();
2021-06-11 12:02:28 +00:00
+ if (packetLength > MAX_PACKET_SIZE) {
+ throw new PacketTooLargeException(packet, packetLength);
+ }
+ // Paper end
}
}
}
+
+ // Paper start
+ private static int MAX_PACKET_SIZE = 2097152;
+
+ public static class PacketTooLargeException extends RuntimeException {
+ private final Packet<?> packet;
+
+ PacketTooLargeException(Packet<?> packet, int packetLength) {
+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE);
+ this.packet = packet;
+ }
+
+ public Packet<?> getPacket() {
+ return packet;
+ }
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
2021-06-13 08:26:58 +00:00
index 10c1f2d8a92f848c3f2be9d1d06fd254978e6dcc..74bfe0d3942259c45702b099efdc4e101a4e3022 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
2021-06-13 08:26:58 +00:00
@@ -8,6 +8,12 @@ public interface Packet<T extends PacketListener> {
2021-06-11 12:02:28 +00:00
void handle(T listener);
+ // Paper start
2021-06-13 08:26:58 +00:00
+ default boolean packetTooLarge(net.minecraft.network.Connection manager) {
2021-06-11 12:02:28 +00:00
+ return false;
+ }
+ // Paper end
+
default boolean isSkippable() {
return false;
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
index 0e076173033278587df2b5dfbd01cc9005651eb5..dbd8b9b09b82c1b75e8be9dc7416d9f0863c8c87 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
2021-07-07 06:52:40 +00:00
@@ -31,6 +31,16 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
this.carriedItem = buf.readItem();
}
2021-06-11 12:02:28 +00:00
+ // Paper start
2021-06-11 12:02:28 +00:00
+ @Override
2021-06-13 08:26:58 +00:00
+ public boolean packetTooLarge(net.minecraft.network.Connection manager) {
2021-06-11 12:02:28 +00:00
+ for (int i = 0 ; i < this.items.size() ; i++) {
2021-07-07 06:52:40 +00:00
+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, this.stateId, i, this.items.get(i)));
2021-06-11 12:02:28 +00:00
+ }
+ return true;
+ }
+ // Paper end
2021-06-13 08:26:58 +00:00
+
2021-07-07 06:52:40 +00:00
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(this.containerId);
2021-11-24 00:20:31 +00:00
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
2022-06-10 14:15:38 +00:00
index cc2f53fba1e5f6b6d4d31081ddaca1ace70abf99..fef3507dbaeb963ba4132ab7beb26d22ec39d425 100644
2021-11-24 00:20:31 +00:00
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -50,7 +50,7 @@ public class ClientboundLevelChunkPacketData {
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
2021-06-11 12:02:28 +00:00
} else {
2021-06-13 08:26:58 +00:00
int i = buf.readVarInt();
- if (i > 2097152) {
+ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.buffer = new byte[i];