Skip to content

Commit 245433b

Browse files
committed
Fix server pings and the infamous closed channel exception
As a result, packet listeners for OUT_SERVER_INFO will be processed on the netty server io thread, so they will have to be thread safe if they aren't already. Fixes #119
1 parent 9433ea5 commit 245433b

File tree

5 files changed

+23
-82
lines changed

5 files changed

+23
-82
lines changed

ProtocolLib/src/main/java/com/comphenix/protocol/PacketType.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public static class Status {
269269
public static class Server extends ObjectEnum<PacketType> {
270270
private final static Sender SENDER = Sender.SERVER;
271271

272-
public static final PacketType OUT_SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 255);
272+
public static final PacketType OUT_SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 255).forceAsync(true);
273273
public static final PacketType OUT_PING = new PacketType(PROTOCOL, SENDER, 0x01, 230);
274274

275275
private final static Server INSTANCE = new Server();
@@ -523,7 +523,8 @@ public ConnectionSide toSide() {
523523
private final int currentId;
524524
private final int legacyId;
525525
private final MinecraftVersion version;
526-
private final boolean dynamic;
526+
private boolean forceAsync;
527+
private boolean dynamic;
527528

528529
/**
529530
* Retrieve the current packet/legacy lookup.
@@ -679,7 +680,8 @@ public static PacketType fromCurrent(Protocol protocol, Sender sender, int packe
679680
PacketType type = getLookup().getFromCurrent(protocol, sender, packetId);
680681

681682
if (type == null) {
682-
type = new PacketType(protocol, sender, packetId, legacyId, PROTOCOL_VERSION, true);
683+
type = new PacketType(protocol, sender, packetId, legacyId, PROTOCOL_VERSION);
684+
type.dynamic = true;
683685

684686
// Many may be scheduled, but only the first will be executed
685687
scheduleRegister(type, "Dynamic-" + UUID.randomUUID().toString());
@@ -798,25 +800,11 @@ public PacketType(Protocol protocol, Sender sender, int currentId, int legacyId)
798800
* @param version - the version of the current ID.
799801
*/
800802
public PacketType(Protocol protocol, Sender sender, int currentId, int legacyId, MinecraftVersion version) {
801-
this(protocol, sender, currentId, legacyId, version, false);
802-
}
803-
804-
/**
805-
* Construct a new packet type.
806-
* @param protocol - the current protocol.
807-
* @param sender - client or server.
808-
* @param currentId - the current packet ID.
809-
* @param legacyId - the legacy packet ID.
810-
* @param version - the version of the current ID.
811-
* @param dynamic - if this type was created dynamically.
812-
*/
813-
public PacketType(Protocol protocol, Sender sender, int currentId, int legacyId, MinecraftVersion version, boolean dynamic) {
814803
this.protocol = Preconditions.checkNotNull(protocol, "protocol cannot be NULL");
815804
this.sender = Preconditions.checkNotNull(sender, "sender cannot be NULL");
816805
this.currentId = currentId;
817806
this.legacyId = legacyId;
818807
this.version = version;
819-
this.dynamic = dynamic;
820808
}
821809

822810
/**
@@ -920,13 +908,26 @@ public int getLegacyId() {
920908
}
921909

922910
/**
923-
* Whether or not this packet was dynamically created (ie we don't have it registered)
911+
* Whether or not this packet was dynamically created (i.e. we don't have it registered)
924912
* @return True if dnyamic, false if not.
925913
*/
926914
public boolean isDynamic() {
927915
return dynamic;
928916
}
929917

918+
private PacketType forceAsync(boolean forceAsync) {
919+
this.forceAsync = forceAsync;
920+
return this;
921+
}
922+
923+
/**
924+
* Whether or not this packet must be processed asynchronously.
925+
* @return True if it must be, false if not.
926+
*/
927+
public boolean forceAsync() {
928+
return forceAsync;
929+
}
930+
930931
@Override
931932
public int hashCode() {
932933
return Objects.hashCode(protocol, sender, currentId, legacyId);

ProtocolLib/src/main/java/com/comphenix/protocol/compat/netty/independent/NettyChannelInjector.java

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,19 @@
1919
import io.netty.buffer.ByteBuf;
2020
import io.netty.channel.Channel;
2121
import io.netty.channel.ChannelHandler;
22-
import io.netty.channel.ChannelHandlerAdapter;
2322
import io.netty.channel.ChannelHandlerContext;
2423
import io.netty.channel.ChannelInboundHandlerAdapter;
2524
import io.netty.channel.ChannelPipeline;
2625
import io.netty.channel.ChannelPromise;
2726
import io.netty.channel.socket.SocketChannel;
2827
import io.netty.handler.codec.ByteToMessageDecoder;
2928
import io.netty.handler.codec.MessageToByteEncoder;
30-
import io.netty.util.ReferenceCountUtil;
3129
import io.netty.util.concurrent.GenericFutureListener;
3230
import io.netty.util.internal.TypeParameterMatcher;
3331

3432
import java.lang.reflect.InvocationTargetException;
3533
import java.net.Socket;
3634
import java.net.SocketAddress;
37-
import java.nio.channels.ClosedChannelException;
3835
import java.util.ArrayDeque;
3936
import java.util.Deque;
4037
import java.util.List;
@@ -283,37 +280,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
283280
}
284281
};
285282

286-
ChannelHandlerAdapter exceptionHandler = new ChannelHandlerAdapter() {
287-
@Override
288-
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
289-
if (channelListener.isDebug()) {
290-
// People were complaining about this on the forums, figure I might as well figure out the cause
291-
System.out.println("------------ ProtocolLib Debug ------------");
292-
System.out.println("Caught an exception in " + playerName + "\'s channel pipeline.");
293-
System.out.println("Context: " + ctx);
294-
System.out.println("The exception was: " + cause);
295-
System.out.println("Stack trace:");
296-
cause.printStackTrace(System.out);
297-
System.out.println("Please create an issue on GitHub with the above message.");
298-
System.out.println("https://github.com/dmulloy2/ProtocolLib/issues");
299-
System.out.println("-------------------------------------------");
300-
}
301-
302-
if (cause instanceof ClosedChannelException) {
303-
// This is what the DefaultChannelPipeline does
304-
ReferenceCountUtil.release(cause);
305-
} else {
306-
// We only care about closed channel exceptions, pass everything else along
307-
super.exceptionCaught(ctx, cause);
308-
}
309-
}
310-
};
311-
312283
// Insert our handlers - note that we effectively replace the vanilla encoder/decoder
313284
originalChannel.pipeline().addBefore("decoder", "protocol_lib_decoder", this);
314285
originalChannel.pipeline().addBefore("protocol_lib_decoder", "protocol_lib_finish", finishHandler);
315286
originalChannel.pipeline().addAfter("encoder", "protocol_lib_encoder", protocolEncoder);
316-
originalChannel.pipeline().addLast("protocol_lib_exception_handler", exceptionHandler);
317287

318288
// Intercept all write methods
319289
channelField.setValue(new NettyChannelProxy(originalChannel, MinecraftReflection.getPacketClass()) {
@@ -840,7 +810,7 @@ public void close() {
840810
@Override
841811
public void run() {
842812
String[] handlers = new String[] {
843-
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder", "protocol_lib_exception_handler"
813+
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder"
844814
};
845815

846816
for (String handler : handlers) {

ProtocolLib/src/main/java/com/comphenix/protocol/compat/netty/independent/NettyProtocolInjector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public boolean uninjectPlayer(InetSocketAddress address) {
356356

357357
@Override
358358
public void addPacketHandler(PacketType type, Set<ListenerOptions> options) {
359-
if (options != null && !options.contains(ListenerOptions.ASYNC))
359+
if (options != null && !type.forceAsync() && !options.contains(ListenerOptions.ASYNC))
360360
mainThreadFilters.addType(type);
361361
super.addPacketHandler(type, options);
362362
}

modules/v1_7_R4/src/main/java/com/comphenix/protocol/compat/netty/shaded/ShadedChannelInjector.java

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.lang.reflect.InvocationTargetException;
2020
import java.net.Socket;
2121
import java.net.SocketAddress;
22-
import java.nio.channels.ClosedChannelException;
2322
import java.util.ArrayDeque;
2423
import java.util.Deque;
2524
import java.util.List;
@@ -32,15 +31,13 @@
3231
import net.minecraft.util.io.netty.buffer.ByteBuf;
3332
import net.minecraft.util.io.netty.channel.Channel;
3433
import net.minecraft.util.io.netty.channel.ChannelHandler;
35-
import net.minecraft.util.io.netty.channel.ChannelHandlerAdapter;
3634
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
3735
import net.minecraft.util.io.netty.channel.ChannelInboundHandlerAdapter;
3836
import net.minecraft.util.io.netty.channel.ChannelPipeline;
3937
import net.minecraft.util.io.netty.channel.ChannelPromise;
4038
import net.minecraft.util.io.netty.channel.socket.SocketChannel;
4139
import net.minecraft.util.io.netty.handler.codec.ByteToMessageDecoder;
4240
import net.minecraft.util.io.netty.handler.codec.MessageToByteEncoder;
43-
import net.minecraft.util.io.netty.util.ReferenceCountUtil;
4441
import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener;
4542
import net.minecraft.util.io.netty.util.internal.TypeParameterMatcher;
4643
import net.sf.cglib.proxy.Factory;
@@ -282,37 +279,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
282279
}
283280
};
284281

285-
ChannelHandlerAdapter exceptionHandler = new ChannelHandlerAdapter() {
286-
@Override
287-
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
288-
if (channelListener.isDebug()) {
289-
// People were complaining about this on the forums, figure I might as well figure out the cause
290-
System.out.println("------------ ProtocolLib Debug ------------");
291-
System.out.println("Caught an exception in " + playerName + "\'s channel pipeline.");
292-
System.out.println("Context: " + ctx);
293-
System.out.println("The exception was: " + cause);
294-
System.out.println("Stack trace:");
295-
cause.printStackTrace(System.out);
296-
System.out.println("Please create an issue on GitHub with the above message.");
297-
System.out.println("https://github.com/dmulloy2/ProtocolLib/issues");
298-
System.out.println("-------------------------------------------");
299-
}
300-
301-
if (cause instanceof ClosedChannelException) {
302-
// This is what the DefaultChannelPipeline does
303-
ReferenceCountUtil.release(cause);
304-
} else {
305-
// We only care about closed channel exceptions, pass everything else along
306-
super.exceptionCaught(ctx, cause);
307-
}
308-
}
309-
};
310-
311282
// Insert our handlers - note that we effectively replace the vanilla encoder/decoder
312283
originalChannel.pipeline().addBefore("decoder", "protocol_lib_decoder", this);
313284
originalChannel.pipeline().addBefore("protocol_lib_decoder", "protocol_lib_finish", finishHandler);
314285
originalChannel.pipeline().addAfter("encoder", "protocol_lib_encoder", protocolEncoder);
315-
originalChannel.pipeline().addLast("protocol_lib_exception_handler", exceptionHandler);
316286

317287
// Intercept all write methods
318288
channelField.setValue(new ShadedChannelProxy(originalChannel, MinecraftReflection.getPacketClass()) {
@@ -839,7 +809,7 @@ public void close() {
839809
@Override
840810
public void run() {
841811
String[] handlers = new String[] {
842-
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder", "protocol_lib_exception_handler"
812+
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder"
843813
};
844814

845815
for (String handler : handlers) {

modules/v1_7_R4/src/main/java/com/comphenix/protocol/compat/netty/shaded/ShadedProtocolInjector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public boolean uninjectPlayer(InetSocketAddress address) {
356356

357357
@Override
358358
public void addPacketHandler(PacketType type, Set<ListenerOptions> options) {
359-
if (options != null && !options.contains(ListenerOptions.ASYNC))
359+
if (options != null && !type.forceAsync() && !options.contains(ListenerOptions.ASYNC))
360360
mainThreadFilters.addType(type);
361361
super.addPacketHandler(type, options);
362362
}

0 commit comments

Comments
 (0)