Skip to content

Commit

Permalink
Adjust large packet handler to run when above protocol limit
Browse files Browse the repository at this point in the history
Previously, PacketEncoder assumed that a packet value larger
than the protocol limit would be compressed to become smaller
than the protocol limit. However, not all packets will compress
below the protocol limit.

To try to better handle this, we will run the large packet handler
when the packet size is above the protocol limit when the packet
has a large packet fallback to avoid a case where the packet
does not compress below protocol limit (at which point, it is
too late to run the large packet handler).
  • Loading branch information
Spottedleaf committed Apr 23, 2024
1 parent f4c7d37 commit 53d10b8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ index 02b3f5c67b47a098f7fe15ddba0df6cb586a9ae5..157f055df00faf3a7870df8109e84fdb
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
index 0d80fcee1831af59b06c4d00dc713bd4dad947fc..061eada043325142d33a0cec02e9e484d14a7fca 100644
index 0d80fcee1831af59b06c4d00dc713bd4dad947fc..3fe047a6ea4eedb92a795dc747d30c0815c2baf2 100644
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
@@ -41,7 +41,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
Expand All @@ -46,13 +46,13 @@ index 0d80fcee1831af59b06c4d00dc713bd4dad947fc..061eada043325142d33a0cec02e9e484
throw new IllegalArgumentException("Packet too big (is " + k + ", should be less than 8388608): " + packet);
}

@@ -54,9 +54,34 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
@@ -54,9 +54,37 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {

throw var13;
} finally {
+ // Paper start - Handle large packets disconnecting client
+ int packetLength = friendlyByteBuf.readableBytes();
+ if (packetLength > MAX_PACKET_SIZE) {
+ if (packetLength > MAX_PACKET_SIZE || (packetLength > MAX_FINAL_PACKET_SIZE && packet.hasLargePacketFallback())) {
+ throw new PacketTooLargeException(packet, this.codecKey, packetLength);
+ }
+ // Paper end - Handle large packets disconnecting client
Expand All @@ -63,7 +63,10 @@ index 0d80fcee1831af59b06c4d00dc713bd4dad947fc..061eada043325142d33a0cec02e9e484
}
+
+ // Paper start
+ private static int MAX_PACKET_SIZE = 8388608;
+ // packet size is encoded into 3-byte varint
+ private static final int MAX_FINAL_PACKET_SIZE = (1 << 21) - 1;
+ // Vanilla Max size for the encoder (before compression)
+ private static final int MAX_PACKET_SIZE = 8388608;
+
+ public static class PacketTooLargeException extends RuntimeException {
+ private final Packet<?> packet;
Expand All @@ -82,14 +85,21 @@ index 0d80fcee1831af59b06c4d00dc713bd4dad947fc..061eada043325142d33a0cec02e9e484
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
index 700418bb0c9fbed3f161611881b1e222248ca4eb..cc658a61065d5c0021a4b88fa58b40211b94f8ec 100644
index 700418bb0c9fbed3f161611881b1e222248ca4eb..c920bf67002f1ca969b5e1559cdfdc2704dead4b 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -10,6 +10,12 @@ public interface Packet<T extends PacketListener> {
@@ -10,6 +10,19 @@ public interface Packet<T extends PacketListener> {

void handle(T listener);

+ // Paper start
+ default boolean hasLargePacketFallback() {
+ return false;
+ }
+
+ /**
+ * override {@link #hasLargePacketFallback()} to return true when overriding in subclasses
+ */
+ default boolean packetTooLarge(net.minecraft.network.Connection manager) {
+ return false;
+ }
Expand All @@ -99,15 +109,20 @@ index 700418bb0c9fbed3f161611881b1e222248ca4eb..cc658a61065d5c0021a4b88fa58b4021
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 6206d4d71dfe95b454b22f5b3055623638e145c0..6765175c98d52e5cbc191e88e0d545a05606dfd4 100644
index 6206d4d71dfe95b454b22f5b3055623638e145c0..3d52fd6de8b33e45450bb601697920bf94493fb9 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
@@ -31,6 +31,16 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
@@ -31,6 +31,21 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
this.carriedItem = buf.readItem();
}

+ // Paper start
+ @Override
+ public boolean hasLargePacketFallback() {
+ return true;
+ }
+
+ @Override
+ public boolean packetTooLarge(net.minecraft.network.Connection manager) {
+ for (int i = 0 ; i < this.items.size() ; i++) {
+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, this.stateId, i, this.items.get(i)));
Expand All @@ -120,7 +135,7 @@ index 6206d4d71dfe95b454b22f5b3055623638e145c0..6765175c98d52e5cbc191e88e0d545a0
public void write(FriendlyByteBuf buf) {
buf.writeByte(this.containerId);
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 0c593b7a4e893568db9c1b0b5dfa7ee4984cd8c9..99fe90094f1cabdaea9db89cfc016a98c1ee8c2d 100644
index dc657312889da4fc3222a6981223a01406b77deb..a44a82d2d5ed4d675dc1a184d5b6b935fda575dd 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -49,7 +49,7 @@ public class ClientboundLevelChunkPacketData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,13 +333,14 @@ index c399625a342ffd61102bb96a97ac24b0669e8e17..16eb94eb1f40485daef2713f740f6e0b
+ // Paper end - Optimize network
}
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
index cc658a61065d5c0021a4b88fa58b40211b94f8ec..da11266a0a23f446196e6facf2c358cfcc18070f 100644
index c920bf67002f1ca969b5e1559cdfdc2704dead4b..f82702c9b1aefedb3c3ce35d4f93836ec24b488f 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -11,6 +11,30 @@ public interface Packet<T extends PacketListener> {
void handle(T listener);

// Paper start
@@ -21,6 +21,31 @@ public interface Packet<T extends PacketListener> {
default boolean packetTooLarge(net.minecraft.network.Connection manager) {
return false;
}
+
+ /**
+ * @param player Null if not at PLAY stage yet
+ */
Expand All @@ -364,9 +365,9 @@ index cc658a61065d5c0021a4b88fa58b40211b94f8ec..da11266a0a23f446196e6facf2c358cf
+ default java.util.List<Packet<?>> getExtraPackets() {
+ return null;
+ }
default boolean packetTooLarge(net.minecraft.network.Connection manager) {
return false;
}
// Paper end

default boolean isSkippable() {
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index 4f330a44c77a7ec3237a86fda04921a8c4a1c00f..a4a29a7ea0035ecf4c61ee8547a9eb24acb667d0 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
Expand Down

0 comments on commit 53d10b8

Please sign in to comment.