Paper/Spigot-Server-Patches/0412-Handle-Large-Packets-disconnecting-client.patch
Shane Freeder 0318e62b45
Updated Upstream (Bukkit/CraftBukkit)
Upstream has released updates that appears 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:
0969eedc Clarify furnace burn time behaviour as per SPIGOT-844
16453bfd SPIGOT-4503: Add API to insert complete ItemStack into Jukebox

CraftBukkit Changes:
dff66dfc Reduce copying of positions from block states
91cae6ef SPIGOT-4387: Durability looping from cancelled BlockPlaceEvent
24c5e68c SPIGOT-4493: Allow burnt out furnaces to remain lit like Vanilla whilst retaining SPIGOT-844 API
bc943daf Fix Jukebox API not synchronizing playing data with state
fe89a8c1 SPIGOT-4503: Add API to insert complete ItemStack into Jukebox
fc102494 Make CraftBlockState use BlockPosition
89ab4887 SPIGOT-4543: Jukebox playing calls should not use legacy data
6ff5a64c SPIGOT-4541: Cancelled bucket events require inventory update
2018-12-23 17:04:13 +00:00

119 lines
4.8 KiB
Diff

From a8b39ea15fbb0ad46e7b7c1726499390f351d947 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/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java
index 120416b30..065bede4c 100644
--- a/src/main/java/net/minecraft/server/NetworkManager.java
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
@@ -100,6 +100,15 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
}
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
+ // Paper start
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) {
+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) {
+ return;
+ } else {
+ throwable = throwable.getCause();
+ }
+ }
+ // Paper end
if (throwable instanceof SkipEncodeException) {
NetworkManager.g.debug("Skipping packet due to errors", throwable.getCause());
} else {
diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java
index 2e42c268b..0a9bfb07a 100644
--- a/src/main/java/net/minecraft/server/Packet.java
+++ b/src/main/java/net/minecraft/server/Packet.java
@@ -9,6 +9,12 @@ public interface Packet<T extends PacketListener> {
void a(T var1);
+ // Paper start
+ default boolean packetTooLarge(NetworkManager manager) {
+ return false;
+ }
+ // Paper end
+
default boolean a() {
return false;
}
diff --git a/src/main/java/net/minecraft/server/PacketEncoder.java b/src/main/java/net/minecraft/server/PacketEncoder.java
index 3448f6c53..484131e65 100644
--- a/src/main/java/net/minecraft/server/PacketEncoder.java
+++ b/src/main/java/net/minecraft/server/PacketEncoder.java
@@ -45,8 +45,31 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
throw throwable;
}
}
+
+ // Paper start
+ int packetLength = bytebuf.readableBytes();
+ 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/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
index 40ec398ee..ca6bcd22f 100644
--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
+++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
@@ -68,7 +68,7 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> {
this.f = packetdataserializer.readBoolean();
this.c = packetdataserializer.g();
int i = packetdataserializer.g();
- if (i > 2097152) {
+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.d = new byte[i];
diff --git a/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java
index 4d4835353..abdb21f6b 100644
--- a/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java
+++ b/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java
@@ -7,6 +7,16 @@ public class PacketPlayOutWindowItems implements Packet<PacketListenerPlayOut> {
private int a;
private List<ItemStack> b;
+ //Paper start
+ @Override
+ public boolean packetTooLarge(NetworkManager manager) {
+ for (int i = 0 ; i < this.b.size() ; i++) {
+ manager.sendPacket(new PacketPlayOutSetSlot(this.a, i, this.b.get(i)));
+ }
+ return true;
+ }
+ // Paper end
+
public PacketPlayOutWindowItems() {
}
--
2.20.1