aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0284-Handle-Large-Packets-disconnecting-client.patch
blob: 52dc146bd6fe2c72702a488b2ee06cf8989b142f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
index 7065d8e2b0782f1dbaf9932db9201b94ae455a31..f5106ed464d496420ac575b09d6c9a7dfeb87bec 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -158,6 +158,18 @@ public class Connection 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 packetTooLargeException) {
+            if (packetTooLargeException.getPacket().packetTooLarge(this)) {
+                return;
+            } else if (packetTooLargeException.getPacket().isSkippable()) {
+                Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
+                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
index 42828edf81bd475b673a9d143f79c0d0711f14f5..fbfadeb83719b81f42724e79c59e92ed88fdece7 100644
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
@@ -40,7 +40,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
                     int j = friendlyByteBuf.writerIndex();
                     packet.write(friendlyByteBuf);
                     int k = friendlyByteBuf.writerIndex() - j;
-                    if (k > 8388608) {
+                    if (false && k > 8388608) { // Paper - disable
                         throw new IllegalArgumentException("Packet too big (is " + k + ", should be less than 8388608): " + packet);
                     } else {
                         int l = channelHandlerContext.channel().attr(Connection.ATTRIBUTE_PROTOCOL).get().getId();
@@ -54,7 +54,31 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
                         throw var10;
                     }
                 }
+
+                // Paper start
+                int packetLength = friendlyByteBuf.readableBytes();
+                if (packetLength > MAX_PACKET_SIZE) {
+                    throw new PacketTooLargeException(packet, packetLength);
+                }
+                // Paper end
             }
         }
     }
+
+    // Paper start
+    private static int MAX_PACKET_SIZE = 8388608;
+
+    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
index 10c1f2d8a92f848c3f2be9d1d06fd254978e6dcc..74bfe0d3942259c45702b099efdc4e101a4e3022 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -8,6 +8,12 @@ public interface Packet<T extends PacketListener> {
 
     void handle(T listener);
 
+    // Paper start
+    default boolean packetTooLarge(net.minecraft.network.Connection manager) {
+        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
--- 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
         this.carriedItem = buf.readItem();
     }
 
+    // Paper start
+    @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)));
+        }
+        return true;
+    }
+    // Paper end
+
     @Override
     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 932cca4d957c1fc212b7a514ea23e8dc7ab5b9d9..f47eeb70661661610ef1a96dd9da67785825c126 100644
--- 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 + "]");
         } else {
             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];