Skip to content

Commit debdd6d

Browse files
dmulloy2Spagles
andcommitted
Fix async packet handling and utility edge cases
Co-authored-by: Spagles <106791090+Spagles@users.noreply.github.com>
1 parent 2c53c29 commit debdd6d

9 files changed

Lines changed: 109 additions & 20 deletions

File tree

‎src/main/java/com/comphenix/protocol/async/AsyncFilterManager.java‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,10 @@ public synchronized void enqueueSyncPacket(PacketEvent syncPacket, AsyncMarker a
309309

310310
asyncMarker.setQueuedSendingIndex(asyncMarker.getNewSendingIndex());
311311

312-
// The player is only be null when they're logged out,
313-
// so this should be a pretty safe check
314-
Player player = syncPacket.getPlayer();
315-
if (player != null) {
312+
PacketSendingQueue sendingQueue = getSendingQueue(syncPacket);
313+
if (sendingQueue != null) {
316314
// Start the process
317-
getSendingQueue(syncPacket).enqueue(newEvent);
315+
sendingQueue.enqueue(newEvent);
318316

319317
// We know this is occurring on the main thread, so pass TRUE
320318
getProcessingQueue(syncPacket).enqueue(newEvent, true);
@@ -323,12 +321,12 @@ public synchronized void enqueueSyncPacket(PacketEvent syncPacket, AsyncMarker a
323321

324322
@Override
325323
public Set<PacketType> getReceivingTypes() {
326-
return serverProcessingQueue.keySet();
324+
return clientProcessingQueue.keySet();
327325
}
328326

329327
@Override
330328
public Set<PacketType> getSendingTypes() {
331-
return clientProcessingQueue.keySet();
329+
return serverProcessingQueue.keySet();
332330
}
333331

334332
/**

‎src/main/java/com/comphenix/protocol/async/PlayerSendingHandler.java‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,18 @@ public PacketSendingQueue getSendingQueue(PacketEvent packet) {
134134
* @return The server or client sending queue the packet belongs to.
135135
*/
136136
public PacketSendingQueue getSendingQueue(PacketEvent packet, boolean createNew) {
137-
QueueContainer queues = playerSendingQueues.get(packet.getPlayer());
137+
Player player = packet.getPlayer();
138+
if (player == null)
139+
return null;
140+
141+
QueueContainer queues = playerSendingQueues.get(player);
138142

139143
// Safe concurrent initialization
140144
if (queues == null && createNew) {
141145
final QueueContainer newContainer = new QueueContainer();
142146

143147
// Attempt to map the queue
144-
queues = playerSendingQueues.putIfAbsent(packet.getPlayer(), newContainer);
148+
queues = playerSendingQueues.putIfAbsent(player, newContainer);
145149

146150
if (queues == null) {
147151
queues = newContainer;

‎src/main/java/com/comphenix/protocol/collections/IntegerMap.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public T put(int key, T value) {
5858
* @return The old associated value, or NULL.
5959
*/
6060
public T remove(int key) {
61+
if (key < 0 || key >= array.length) return null;
62+
6163
T old = array[key];
6264
array[key] = null;
6365

‎src/main/java/com/comphenix/protocol/concurrency/ConcurrentPlayerMap.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ private Object cachePlayerKey(Player player) {
190190
Preconditions.checkNotNull(player, "player cannot be null");
191191

192192
Object key = keyMethod.apply(player);
193-
193+
Preconditions.checkState(key != null, "Unable to derive a key for the player.");
194+
194195
keyLookup.put(key, player);
195196
return key;
196197
}

‎src/main/java/com/comphenix/protocol/utility/StreamSerializer.java‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,9 @@ public void serializeItemStack(DataOutputStream output, ItemStack stack) throws
326326

327327
public byte[] getBytesAndRelease(ByteBuf buf) {
328328
try {
329-
if (buf.hasArray()) {
330-
// heap buffer, we can access the array directly
331-
return buf.array();
332-
} else {
333-
// direct buffer, we need to copy the bytes into an array
334-
byte[] bytes = new byte[buf.readableBytes()];
335-
buf.readBytes(bytes);
336-
return bytes;
337-
}
329+
byte[] bytes = new byte[buf.readableBytes()];
330+
buf.getBytes(buf.readerIndex(), bytes);
331+
return bytes;
338332
} finally {
339333
ReferenceCountUtil.safeRelease(buf);
340334
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.comphenix.protocol.async;
2+
3+
import com.comphenix.protocol.BukkitInitialization;
4+
import com.comphenix.protocol.PacketType;
5+
import com.comphenix.protocol.ProtocolManager;
6+
import com.comphenix.protocol.error.ErrorReporter;
7+
import com.comphenix.protocol.events.PacketAdapter;
8+
import com.comphenix.protocol.scheduler.ProtocolScheduler;
9+
10+
import org.bukkit.plugin.Plugin;
11+
import org.junit.jupiter.api.BeforeAll;
12+
import org.junit.jupiter.api.Test;
13+
14+
import static org.junit.jupiter.api.Assertions.assertFalse;
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
16+
import static org.mockito.Mockito.mock;
17+
18+
class AsyncFilterManagerTest {
19+
20+
@BeforeAll
21+
static void initializeBukkit() {
22+
BukkitInitialization.initializeAll();
23+
}
24+
25+
@Test
26+
void testSendingTypesUseServerProcessingQueue() {
27+
AsyncFilterManager manager = new AsyncFilterManager(
28+
mock(ErrorReporter.class), mock(ProtocolScheduler.class));
29+
manager.setManager(mock(ProtocolManager.class));
30+
manager.registerAsyncHandler(new PacketAdapter(
31+
mock(Plugin.class), PacketType.Play.Server.SYSTEM_CHAT) { }, false);
32+
33+
assertTrue(manager.getSendingTypes().contains(PacketType.Play.Server.SYSTEM_CHAT));
34+
assertFalse(manager.getReceivingTypes().contains(PacketType.Play.Server.SYSTEM_CHAT));
35+
}
36+
}

‎src/test/java/com/comphenix/protocol/collections/IntegerMapTest.java‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.junit.jupiter.api.Test;
66

77
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
import static org.junit.jupiter.api.Assertions.assertNull;
89

910
class IntegerMapTest {
1011
@Test
@@ -21,4 +22,15 @@ public void testCapacityIncrement() {
2122
}
2223
assertEquals(map.size(), 512);
2324
}
24-
}
25+
26+
@Test
27+
public void testRemoveOutsideBounds() {
28+
IntegerMap<Boolean> map = new IntegerMap<>();
29+
map.put(0, true);
30+
31+
assertNull(map.remove(-1));
32+
assertEquals(1, map.size());
33+
assertNull(map.remove(8));
34+
assertEquals(1, map.size());
35+
}
36+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.comphenix.protocol.concurrency;
2+
3+
import org.bukkit.entity.Player;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertThrows;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
8+
import static org.mockito.Mockito.mock;
9+
10+
class ConcurrentPlayerMapTest {
11+
12+
@Test
13+
void testPutIfAbsentWithUnavailableAddress() {
14+
ConcurrentPlayerMap<Object> map = ConcurrentPlayerMap.usingAddress();
15+
Player player = mock(Player.class);
16+
17+
assertThrows(IllegalStateException.class, () -> map.putIfAbsent(player, new Object()));
18+
assertTrue(map.isEmpty());
19+
}
20+
}

‎src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
1111
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
1212

13+
import io.netty.buffer.ByteBuf;
14+
import io.netty.buffer.Unpooled;
1315
import org.bukkit.ChatColor;
1416
import org.bukkit.Material;
1517
import org.bukkit.inventory.ItemStack;
@@ -19,6 +21,7 @@
1921

2022
import static com.comphenix.protocol.utility.TestUtils.assertItemsEqual;
2123

24+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2225
import static org.junit.jupiter.api.Assertions.assertEquals;
2326

2427
public class StreamSerializerTest {
@@ -86,4 +89,23 @@ public void testItemMeta() throws IOException {
8689

8790
assertItemsEqual(initial, deserialized);
8891
}
92+
93+
@Test
94+
public void testGetBytesAndReleasePreservesReaderIndex() {
95+
StreamSerializer serializer = new StreamSerializer();
96+
ByteBuf[] buffers = {Unpooled.buffer(16), Unpooled.directBuffer(16)};
97+
98+
for (ByteBuf buffer : buffers) {
99+
buffer.writeBytes(new byte[] {0, 1, 2, 3, 4});
100+
buffer.readerIndex(2);
101+
buffer.retain();
102+
103+
try {
104+
assertArrayEquals(new byte[] {2, 3, 4}, serializer.getBytesAndRelease(buffer));
105+
assertEquals(2, buffer.readerIndex());
106+
} finally {
107+
buffer.release();
108+
}
109+
}
110+
}
89111
}

0 commit comments

Comments
 (0)