From 4a1b8766f17cf6fb96968df7190bcca914a5b0be Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 27 Nov 2018 21:42:42 -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. --- ...e-Large-Packets-disconnecting-client.patch | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch diff --git a/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch b/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 0000000000..de0e909e17 --- /dev/null +++ b/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +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 97a9dffe6..2f887932b 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + 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 +@@ -0,0 +0,0 @@ public interface Packet { + + 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 c20911c96..c22c3eebc 100644 +--- a/src/main/java/net/minecraft/server/PacketEncoder.java ++++ b/src/main/java/net/minecraft/server/PacketEncoder.java +@@ -0,0 +0,0 @@ public class PacketEncoder extends MessageToByteEncoder> { + 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 ++ + // $FF: synthetic method + protected void encode(ChannelHandlerContext channelhandlercontext, Packet object, ByteBuf bytebuf) throws Exception { // Paper - decompiler fix + this.a(channelhandlercontext, (Packet)object, bytebuf); +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 +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { + 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 +@@ -0,0 +0,0 @@ public class PacketPlayOutWindowItems implements Packet { + private int a; + private List 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() { + } + +-- \ No newline at end of file