From 0d7513c4a4187bb0bd8dd7c202036cbfdd9ab42b 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 | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 Spigot-Server-Patches/0415-Handle-Large-Packets-disconnecting-client.patch diff --git a/Spigot-Server-Patches/0415-Handle-Large-Packets-disconnecting-client.patch b/Spigot-Server-Patches/0415-Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 000000000..69164147a --- /dev/null +++ b/Spigot-Server-Patches/0415-Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,119 @@ +From 030ce5b54e606115c3cce607fea5ab7bdd669242 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 +@@ -100,6 +100,15 @@ 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 +@@ -9,6 +9,12 @@ 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 +@@ -45,10 +45,32 @@ 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 +@@ -68,7 +68,7 @@ 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 +@@ -7,6 +7,16 @@ 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() { + } + +-- +2.19.1 +